blob: 9c9fcaf64506d7f207fb04a6e2c531bdaea73fd6 [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 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001081 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1082 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001083 (const xmlChar *) message, NULL);
1084 FREE_AND_NULL(str)
1085 xmlFree(msg);
1086}
1087
1088/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001089 * xmlSchemaVComplexTypeElemErr:
1090 * @ctxt: the schema validation context
1091 * @error: the error code
1092 * @node: the node containing the validated value
1093 * @type: the complex type used for validation
1094 * @message: the error message
1095 *
1096 * Reports a complex type validation error.
1097 */
1098static void
1099xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1100 xmlParserErrors error,
1101 xmlNodePtr node,
1102 xmlSchemaTypePtr type,
1103 const char *message,
1104 int nbval,
1105 int nbneg,
1106 xmlChar **values)
1107{
1108 xmlChar *str = NULL, *msg = NULL;
1109 xmlChar *localName, *nsName;
1110 const xmlChar *cur, *end;
1111 int i;
1112
1113 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1114 /* Specify the complex type only if it is global. */
1115 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1116 msg = xmlStrcat(msg, BAD_CAST " [");
1117 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1118 msg = xmlStrcat(msg, BAD_CAST "]");
1119 FREE_AND_NULL(str)
1120 }
1121 msg = xmlStrcat(msg, BAD_CAST ": ");
1122 msg = xmlStrcat(msg, (const xmlChar *) message);
1123 /*
1124 * Note that is does not make sense to report that we have a
1125 * wildcard here, since the wildcard might be unfolded into
1126 * multiple transitions.
1127 */
1128 if (nbval + nbneg > 0) {
1129 if (nbval + nbneg > 1) {
1130 str = xmlStrdup(BAD_CAST ". Expected is one of ");
1131 } else
1132 str = xmlStrdup(BAD_CAST ". Expected is ");
1133 nsName = NULL;
1134
1135 for (i = 0; i < nbval + nbneg; i++) {
1136 cur = values[i];
1137 /*
1138 * Get the local name.
1139 */
1140 localName = NULL;
1141
1142 end = cur;
1143 if (*end == '*') {
1144 localName = xmlStrdup(BAD_CAST "*");
1145 *end++;
1146 } else {
1147 while ((*end != 0) && (*end != '|'))
1148 end++;
1149 localName = xmlStrcat(localName, BAD_CAST "'");
1150 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
1151 localName = xmlStrcat(localName, BAD_CAST "'");
1152 }
1153 if (*end != 0) {
1154 *end++;
1155 /*
1156 * Skip "*|*" if they come with negated expressions, since
1157 * they represent the same negated wildcard.
1158 */
1159 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1160 /*
1161 * Get the namespace name.
1162 */
1163 cur = end;
1164 if (*end == '*') {
1165 nsName = xmlStrdup(BAD_CAST "{*}");
1166 } else {
1167 while (*end != 0)
1168 end++;
1169
1170 if (i >= nbval)
1171 nsName = xmlStrdup(BAD_CAST "{##other:");
1172 else
1173 nsName = xmlStrdup(BAD_CAST "{");
1174
1175 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1176 nsName = xmlStrcat(nsName, BAD_CAST "}");
1177 }
1178 str = xmlStrcat(str, BAD_CAST nsName);
1179 FREE_AND_NULL(nsName)
1180 } else {
1181 FREE_AND_NULL(localName);
1182 continue;
1183 }
1184 }
1185 str = xmlStrcat(str, BAD_CAST localName);
1186 FREE_AND_NULL(localName);
1187
1188 if (i < nbval + nbneg -1)
1189 str = xmlStrcat(str, BAD_CAST ", ");
1190 }
1191 msg = xmlStrcat(msg, BAD_CAST str);
1192 FREE_AND_NULL(str)
1193 }
1194 msg = xmlStrcat(msg, BAD_CAST ".\n");
1195 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1196 xmlFree(msg);
1197}
1198
1199/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001200 * xmlSchemaPMissingAttrErr:
1201 * @ctxt: the schema validation context
1202 * @ownerDes: the designation of the owner
1203 * @ownerName: the name of the owner
1204 * @ownerItem: the owner as a schema object
1205 * @ownerElem: the owner as an element node
1206 * @node: the parent element node of the missing attribute node
1207 * @type: the corresponding type of the attribute node
1208 *
1209 * Reports an illegal attribute.
1210 */
1211static void
1212xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1213 xmlParserErrors error,
1214 xmlChar **ownerDes,
1215 xmlSchemaTypePtr ownerItem,
1216 xmlNodePtr ownerElem,
1217 const char *name,
1218 const char *message)
1219{
1220 xmlChar *des = NULL;
1221
1222 if (ownerDes == NULL)
1223 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1224 else if (*ownerDes == NULL) {
1225 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1226 des = *ownerDes;
1227 } else
1228 des = *ownerDes;
1229 if (message != NULL)
1230 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1231 else
1232 xmlSchemaPErr(ctxt, ownerElem, error,
1233 "%s: The attribute '%s' is required but missing.\n",
1234 BAD_CAST des, BAD_CAST name);
1235 if (ownerDes == NULL)
1236 FREE_AND_NULL(des);
1237}
1238
William M. Brack2f2a6632004-08-20 23:09:47 +00001239/**
1240 * xmlSchemaCompTypeToString:
1241 * @type: the type of the schema item
1242 *
1243 * Returns the component name of a schema item.
1244 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001245static const char *
1246xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1247{
1248 switch (type) {
1249 case XML_SCHEMA_TYPE_SIMPLE:
1250 return("simple type definition");
1251 case XML_SCHEMA_TYPE_COMPLEX:
1252 return("complex type definition");
1253 case XML_SCHEMA_TYPE_ELEMENT:
1254 return("element declaration");
1255 case XML_SCHEMA_TYPE_ATTRIBUTE:
1256 return("attribute declaration");
1257 case XML_SCHEMA_TYPE_GROUP:
1258 return("model group definition");
1259 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1260 return("attribute group definition");
1261 case XML_SCHEMA_TYPE_NOTATION:
1262 return("notation declaration");
1263 default:
1264 return("Not a schema component");
1265 }
1266}
1267/**
1268 * xmlSchemaPResCompAttrErr:
1269 * @ctxt: the schema validation context
1270 * @error: the error code
1271 * @ownerDes: the designation of the owner
1272 * @ownerItem: the owner as a schema object
1273 * @ownerElem: the owner as an element node
1274 * @name: the name of the attribute holding the QName
1275 * @refName: the referenced local name
1276 * @refURI: the referenced namespace URI
1277 * @message: optional message
1278 *
1279 * Used to report QName attribute values that failed to resolve
1280 * to schema components.
1281 */
1282static void
1283xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1284 xmlParserErrors error,
1285 xmlChar **ownerDes,
1286 xmlSchemaTypePtr ownerItem,
1287 xmlNodePtr ownerElem,
1288 const char *name,
1289 const xmlChar *refName,
1290 const xmlChar *refURI,
1291 xmlSchemaTypeType refType,
1292 const char *refTypeStr)
1293{
1294 xmlChar *des = NULL, *strA = NULL;
1295
1296 if (ownerDes == NULL)
1297 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1298 else if (*ownerDes == NULL) {
1299 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1300 des = *ownerDes;
1301 } else
1302 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001303 if (refTypeStr == NULL)
1304 refTypeStr = xmlSchemaCompTypeToString(refType);
1305 xmlSchemaPErrExt(ctxt, ownerElem, error,
1306 NULL, NULL, NULL,
1307 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1308 "%s.\n", BAD_CAST des, BAD_CAST name,
1309 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1310 BAD_CAST refTypeStr, NULL);
1311 if (ownerDes == NULL)
1312 FREE_AND_NULL(des)
1313 FREE_AND_NULL(strA)
1314}
1315
William M. Brack2f2a6632004-08-20 23:09:47 +00001316/**
1317 * xmlSchemaPCustomAttrErr:
1318 * @ctxt: the schema parser context
1319 * @error: the error code
1320 * @ownerDes: the designation of the owner
1321 * @ownerItem: the owner as a schema object
1322 * @attr: the illegal attribute node
1323 *
1324 * Reports an illegal attribute during the parse.
1325 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001326static void
1327xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001328 xmlParserErrors error,
1329 xmlChar **ownerDes,
1330 xmlSchemaTypePtr ownerItem,
1331 xmlAttrPtr attr,
1332 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001333{
1334 xmlChar *des = NULL;
1335
1336 if (ownerDes == NULL)
1337 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1338 else if (*ownerDes == NULL) {
1339 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1340 des = *ownerDes;
1341 } else
1342 des = *ownerDes;
1343 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1344 "%s, attribute '%s': %s.\n",
1345 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1346 if (ownerDes == NULL)
1347 FREE_AND_NULL(des);
1348}
1349
1350/**
1351 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001352 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001353 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001354 * @ownerDes: the designation of the attribute's owner
1355 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001356 * @attr: the illegal attribute node
1357 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001358 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001359 */
1360static void
1361xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1362 xmlParserErrors error,
1363 xmlChar **ownerDes,
1364 xmlSchemaTypePtr ownerItem,
1365 xmlAttrPtr attr)
1366{
1367 xmlChar *des = NULL, *strA = NULL;
1368
1369 if (ownerDes == NULL)
1370 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1371 else if (*ownerDes == NULL) {
1372 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1373 des = *ownerDes;
1374 } else
1375 des = *ownerDes;
1376 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1377 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1378 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1379 if (ownerDes == NULL)
1380 FREE_AND_NULL(des);
1381 FREE_AND_NULL(strA);
1382}
1383
William M. Brack2f2a6632004-08-20 23:09:47 +00001384/**
1385 * xmlSchemaPAquireDes:
1386 * @des: the first designation
1387 * @itemDes: the second designation
1388 * @item: the schema item
1389 * @itemElem: the node of the schema item
1390 *
1391 * Creates a designation for an item.
1392 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001393static void
1394xmlSchemaPAquireDes(xmlChar **des,
1395 xmlChar **itemDes,
1396 xmlSchemaTypePtr item,
1397 xmlNodePtr itemElem)
1398{
1399 if (itemDes == NULL)
1400 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1401 else if (*itemDes == NULL) {
1402 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1403 *des = *itemDes;
1404 } else
1405 *des = *itemDes;
1406}
1407
William M. Brack2f2a6632004-08-20 23:09:47 +00001408/**
1409 * xmlSchemaPCustomErr:
1410 * @ctxt: the schema parser context
1411 * @error: the error code
1412 * @itemDes: the designation of the schema item
1413 * @item: the schema item
1414 * @itemElem: the node of the schema item
1415 * @message: the error message
1416 * @str1: an optional param for the error message
1417 * @str2: an optional param for the error message
1418 * @str3: an optional param for the error message
1419 *
1420 * Reports an error during parsing.
1421 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001422static void
1423xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1424 xmlParserErrors error,
1425 xmlChar **itemDes,
1426 xmlSchemaTypePtr item,
1427 xmlNodePtr itemElem,
1428 const char *message,
1429 const xmlChar *str1,
1430 const xmlChar *str2,
1431 const xmlChar *str3)
1432{
1433 xmlChar *des = NULL, *msg = NULL;
1434
1435 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1436 msg = xmlStrdup(BAD_CAST "%s: ");
1437 msg = xmlStrcat(msg, (const xmlChar *) message);
1438 msg = xmlStrcat(msg, BAD_CAST ".\n");
1439 if ((itemElem == NULL) && (item != NULL))
1440 itemElem = item->node;
1441 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1442 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1443 if (itemDes == NULL)
1444 FREE_AND_NULL(des);
1445 FREE_AND_NULL(msg);
1446}
1447
William M. Brack2f2a6632004-08-20 23:09:47 +00001448/**
1449 * xmlSchemaPCustomErr:
1450 * @ctxt: the schema parser context
1451 * @error: the error code
1452 * @itemDes: the designation of the schema item
1453 * @item: the schema item
1454 * @itemElem: the node of the schema item
1455 * @message: the error message
1456 * @str1: the optional param for the error message
1457 *
1458 * Reports an error during parsing.
1459 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001460static void
1461xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1462 xmlParserErrors error,
1463 xmlChar **itemDes,
1464 xmlSchemaTypePtr item,
1465 xmlNodePtr itemElem,
1466 const char *message,
1467 const xmlChar *str1)
1468{
1469 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1470 str1, NULL, NULL);
1471}
1472
William M. Brack2f2a6632004-08-20 23:09:47 +00001473/**
1474 * xmlSchemaPAttrUseErr:
1475 * @ctxt: the schema parser context
1476 * @error: the error code
1477 * @itemDes: the designation of the schema type
1478 * @item: the schema type
1479 * @itemElem: the node of the schema type
1480 * @attr: the invalid schema attribute
1481 * @message: the error message
1482 * @str1: the optional param for the error message
1483 *
1484 * Reports an attribute use error during parsing.
1485 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001486static void
1487xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1488 xmlParserErrors error,
1489 xmlChar **itemDes,
1490 xmlSchemaTypePtr item,
1491 xmlNodePtr itemElem,
1492 const xmlSchemaAttributePtr attr,
1493 const char *message,
1494 const xmlChar *str1)
1495{
1496 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1497
1498 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1499 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1500 xmlSchemaGetAttrName(attr));
1501 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1502 msg = xmlStrcat(msg, (const xmlChar *) message);
1503 msg = xmlStrcat(msg, BAD_CAST ".\n");
1504 if ((itemElem == NULL) && (item != NULL))
1505 itemElem = item->node;
1506 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1507 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1508 if (itemDes == NULL)
1509 FREE_AND_NULL(des);
1510 FREE_AND_NULL(strA);
1511 xmlFree(msg);
1512}
1513
William M. Brack2f2a6632004-08-20 23:09:47 +00001514/**
1515 * xmlSchemaPIllegalFacetAtomicErr:
1516 * @ctxt: the schema parser context
1517 * @error: the error code
1518 * @itemDes: the designation of the type
1519 * @item: the schema type
1520 * @baseItem: the base type of type
1521 * @facet: the illegal facet
1522 *
1523 * Reports an illegal facet for atomic simple types.
1524 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001525static void
1526xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1527 xmlParserErrors error,
1528 xmlChar **itemDes,
1529 xmlSchemaTypePtr item,
1530 xmlSchemaTypePtr baseItem,
1531 xmlSchemaFacetPtr facet)
1532{
1533 xmlChar *des = NULL, *strT = NULL;
1534
1535 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1536 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1537 "%s: The facet '%s' is not allowed on types derived from the "
1538 "type %s.\n",
1539 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1540 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1541 NULL, NULL);
1542 if (itemDes == NULL)
1543 FREE_AND_NULL(des);
1544 FREE_AND_NULL(strT);
1545}
1546
William M. Brack2f2a6632004-08-20 23:09:47 +00001547/**
1548 * xmlSchemaPIllegalFacetListUnionErr:
1549 * @ctxt: the schema parser context
1550 * @error: the error code
1551 * @itemDes: the designation of the schema item involved
1552 * @item: the schema item involved
1553 * @facet: the illegal facet
1554 *
1555 * Reports an illegal facet for <list> and <union>.
1556 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001557static void
1558xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1559 xmlParserErrors error,
1560 xmlChar **itemDes,
1561 xmlSchemaTypePtr item,
1562 xmlSchemaFacetPtr facet)
1563{
1564 xmlChar *des = NULL, *strT = NULL;
1565
1566 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1567 xmlSchemaPErr(ctxt, item->node, error,
1568 "%s: The facet '%s' is not allowed.\n",
1569 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1570 if (itemDes == NULL)
1571 FREE_AND_NULL(des);
1572 FREE_AND_NULL(strT);
1573}
1574
1575/**
1576 * xmlSchemaPMutualExclAttrErr:
1577 * @ctxt: the schema validation context
1578 * @error: the error code
1579 * @elemDes: the designation of the parent element node
1580 * @attr: the bad attribute node
1581 * @type: the corresponding type of the attribute node
1582 *
1583 * Reports an illegal attribute.
1584 */
1585static void
1586xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1587 xmlParserErrors error,
1588 xmlChar **ownerDes,
1589 xmlSchemaTypePtr ownerItem,
1590 xmlAttrPtr attr,
1591 const char *name1,
1592 const char *name2)
1593{
1594 xmlChar *des = NULL;
1595
1596 if (ownerDes == NULL)
1597 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1598 else if (*ownerDes == NULL) {
1599 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1600 des = *ownerDes;
1601 } else
1602 des = *ownerDes;
1603 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1604 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1605 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1606 if (ownerDes == NULL)
1607 FREE_AND_NULL(des)
1608}
1609
1610/**
1611 * xmlSchemaPSimpleTypeErr:
1612 * @ctxt: the schema validation context
1613 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001614 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001615 * @ownerDes: the designation of the owner
1616 * @ownerItem: the schema object if existent
1617 * @node: the validated node
1618 * @value: the validated value
1619 *
1620 * Reports a simple type validation error.
1621 * TODO: Should this report the value of an element as well?
1622 */
1623static void
1624xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1625 xmlParserErrors error,
1626 xmlChar **ownerDes,
1627 xmlSchemaTypePtr ownerItem,
1628 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001629 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001630 const char *typeDes,
1631 const xmlChar *value,
1632 const char *message,
1633 const xmlChar *str1,
1634 const xmlChar *str2)
1635{
William M. Brack2f2a6632004-08-20 23:09:47 +00001636 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001637
1638 if (ownerDes == NULL)
1639 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1640 else if (*ownerDes == NULL) {
1641 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1642 des = *ownerDes;
1643 } else
1644 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001645 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001646 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001647 if (message == NULL) {
1648 /*
1649 * Use default messages.
1650 */
1651 if (node->type == XML_ATTRIBUTE_NODE) {
1652 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1653 "%s, attribute '%s' [%s]: The value '%s' is not "
1654 "valid.\n",
1655 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1656 node->name), BAD_CAST typeDes, value, NULL);
1657 } else {
1658 xmlSchemaPErr(ctxt, node, error,
1659 "%s [%s]: The character content is not valid.\n",
1660 BAD_CAST des, BAD_CAST typeDes);
1661 }
1662 } else {
1663 xmlChar *msg;
1664
1665 msg = xmlStrdup(BAD_CAST "%s");
1666 if (node->type == XML_ATTRIBUTE_NODE)
1667 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1668 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1669 msg = xmlStrcat(msg, (const xmlChar *) message);
1670 msg = xmlStrcat(msg, BAD_CAST ".\n");
1671 if (node->type == XML_ATTRIBUTE_NODE) {
1672 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1673 (const char *) msg,
1674 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1675 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1676 } else {
1677 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1678 (const char *) msg,
1679 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1680 }
1681 xmlFree(msg);
1682 }
1683 /* Cleanup. */
1684 FREE_AND_NULL(strA)
1685 FREE_AND_NULL(strT)
1686 if (ownerDes == NULL)
1687 FREE_AND_NULL(des)
1688}
1689
William M. Brack2f2a6632004-08-20 23:09:47 +00001690/**
1691 * xmlSchemaPContentErr:
1692 * @ctxt: the schema parser context
1693 * @error: the error code
1694 * @onwerDes: the designation of the holder of the content
1695 * @ownerItem: the owner item of the holder of the content
1696 * @ownerElem: the node of the holder of the content
1697 * @child: the invalid child node
1698 * @message: the optional error message
1699 * @content: the optional string describing the correct content
1700 *
1701 * Reports an error concerning the content of a schema element.
1702 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001703static void
1704xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1705 xmlParserErrors error,
1706 xmlChar **ownerDes,
1707 xmlSchemaTypePtr ownerItem,
1708 xmlNodePtr ownerElem,
1709 xmlNodePtr child,
1710 const char *message,
1711 const char *content)
1712{
1713 xmlChar *des = NULL;
1714
1715 if (ownerDes == NULL)
1716 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1717 else if (*ownerDes == NULL) {
1718 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1719 des = *ownerDes;
1720 } else
1721 des = *ownerDes;
1722 if (message != NULL)
1723 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1724 "%s: %s.\n",
1725 BAD_CAST des, BAD_CAST message);
1726 else {
1727 if (content != NULL) {
1728 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1729 "%s: The content is not valid. Expected is %s.\n",
1730 BAD_CAST des, BAD_CAST content);
1731 } else {
1732 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1733 "%s: The content is not valid.\n",
1734 BAD_CAST des, NULL);
1735 }
1736 }
1737 if (ownerDes == NULL)
1738 FREE_AND_NULL(des)
1739}
1740
1741/**
1742 * xmlSchemaVIllegalAttrErr:
1743 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001744 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001745 * @attr: the illegal attribute node
1746 *
1747 * Reports an illegal attribute.
1748 */
1749static void
1750xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001751 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001752 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001753{
1754 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001755
1756 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1757 error,
1758 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001759 "%s: The attribute '%s' is not allowed.\n",
1760 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1761 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1762 FREE_AND_NULL(strE)
1763 FREE_AND_NULL(strA)
1764}
1765
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001766
1767static int
1768xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1769{
1770 switch (item->type) {
1771 case XML_SCHEMA_TYPE_COMPLEX:
1772 case XML_SCHEMA_TYPE_SIMPLE:
1773 case XML_SCHEMA_TYPE_GROUP:
1774 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1775 return(1);
1776 break;
1777 case XML_SCHEMA_TYPE_ELEMENT:
1778 if ( ((xmlSchemaElementPtr) item)->flags &
1779 XML_SCHEMAS_ELEM_GLOBAL)
1780 return(1);
1781 break;
1782 case XML_SCHEMA_TYPE_ATTRIBUTE:
1783 if ( ((xmlSchemaAttributePtr) item)->flags &
1784 XML_SCHEMAS_ATTR_GLOBAL)
1785 return(1);
1786 break;
1787 /* Note that attribute groups are always global. */
1788 default:
1789 return(1);
1790 }
1791 return (0);
1792}
1793
William M. Brack2f2a6632004-08-20 23:09:47 +00001794/**
1795 * xmlSchemaVCustomErr:
1796 * @ctxt: the schema validation context
1797 * @error: the error code
1798 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001799 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001800 * @message: the error message
1801 * @str1: the optional param for the message
1802 *
1803 * Reports a validation error.
1804 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001805static void
1806xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1807 xmlParserErrors error,
1808 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001809 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001810 const char *message,
1811 const xmlChar *str1)
1812{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001813 xmlChar *msg = NULL, *str = NULL;
1814
1815 if (node == NULL) {
1816 xmlSchemaVErr(ctxt, NULL,
1817 XML_SCHEMAV_INTERNAL,
1818 "Internal error: xmlSchemaVCustomErr, no node "
1819 "given.\n", NULL, NULL);
1820 return;
1821 }
1822 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1823 if (node->type != XML_DOCUMENT_NODE) {
1824 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001825 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001826 msg = xmlStrcat(msg, BAD_CAST " [");
1827 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1828 msg = xmlStrcat(msg, BAD_CAST "]");
1829 }
1830 msg = xmlStrcat(msg, BAD_CAST ": ");
1831 } else
1832 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001833 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001834 msg = xmlStrcat(msg, BAD_CAST ".\n");
1835 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1836 FREE_AND_NULL(msg)
1837 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001838}
1839
William M. Brack2f2a6632004-08-20 23:09:47 +00001840/**
1841 * xmlSchemaWildcardPCToString:
1842 * @pc: the type of processContents
1843 *
1844 * Returns a string representation of the type of
1845 * processContents.
1846 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001847static const char *
1848xmlSchemaWildcardPCToString(int pc)
1849{
1850 switch (pc) {
1851 case XML_SCHEMAS_ANY_SKIP:
1852 return ("skip");
1853 case XML_SCHEMAS_ANY_LAX:
1854 return ("lax");
1855 case XML_SCHEMAS_ANY_STRICT:
1856 return ("strict");
1857 default:
1858 return ("invalid process contents");
1859 }
1860}
1861
William M. Brack2f2a6632004-08-20 23:09:47 +00001862/**
1863 * xmlSchemaVWildcardErr:
1864 * @ctxt: the schema validation context
1865 * @error: the error code
1866 * @node: the validated node
1867 * @wild: the wildcard used
1868 * @message: the error message
1869 *
1870 * Reports an validation-by-wildcard error.
1871 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001872static void
1873xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1874 xmlParserErrors error,
1875 xmlNodePtr node,
1876 xmlSchemaWildcardPtr wild,
1877 const char *message)
1878{
1879 xmlChar *des = NULL, *msg = NULL;
1880
1881 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1882 msg = xmlStrdup(BAD_CAST "%s, [");
1883 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001884 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001885 msg = xmlStrcat(msg, (const xmlChar *) message);
1886 msg = xmlStrcat(msg, BAD_CAST ".\n");
1887 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1888 FREE_AND_NULL(des);
1889 FREE_AND_NULL(msg);
1890}
1891
1892/**
1893 * xmlSchemaVMissingAttrErr:
1894 * @ctxt: the schema validation context
1895 * @node: the parent element node of the missing attribute node
1896 * @type: the corresponding type of the attribute node
1897 *
1898 * Reports an illegal attribute.
1899 */
1900static void
1901xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1902 xmlNodePtr elem,
1903 xmlSchemaAttributePtr type)
1904{
1905 const xmlChar *name, *uri;
1906 xmlChar *strE = NULL, *strA = NULL;
1907
1908 if (type->ref != NULL) {
1909 name = type->ref;
1910 uri = type->refNs;
1911 } else {
1912 name = type->name;
1913 uri = type->targetNamespace;
1914 }
1915 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001916 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1917 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001918 "%s: The attribute %s is required but missing.\n",
1919 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1920 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1921 FREE_AND_NULL(strE)
1922 FREE_AND_NULL(strA)
1923}
1924
Daniel Veillard4255d502002-04-16 15:50:10 +00001925/************************************************************************
1926 * *
1927 * Allocation functions *
1928 * *
1929 ************************************************************************/
1930
1931/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001932 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001933 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001934 *
1935 * Allocate a new Schema structure.
1936 *
1937 * Returns the newly allocated structure or NULL in case or error
1938 */
1939static xmlSchemaPtr
1940xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1941{
1942 xmlSchemaPtr ret;
1943
1944 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1945 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001946 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001947 return (NULL);
1948 }
1949 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001950 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001951 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001952
1953 return (ret);
1954}
1955
1956/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001957 * xmlSchemaNewSchema:
1958 * @ctxt: a schema validation context
1959 *
1960 * Allocate a new Schema structure.
1961 *
1962 * Returns the newly allocated structure or NULL in case or error
1963 */
1964static xmlSchemaAssemblePtr
1965xmlSchemaNewAssemble(void)
1966{
1967 xmlSchemaAssemblePtr ret;
1968
1969 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1970 if (ret == NULL) {
1971 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1972 return (NULL);
1973 }
1974 memset(ret, 0, sizeof(xmlSchemaAssemble));
1975 ret->items = NULL;
1976 return (ret);
1977}
1978
1979/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001980 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001981 *
1982 * Allocate a new Facet structure.
1983 *
1984 * Returns the newly allocated structure or NULL in case or error
1985 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001986xmlSchemaFacetPtr
1987xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001988{
1989 xmlSchemaFacetPtr ret;
1990
1991 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1992 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001993 return (NULL);
1994 }
1995 memset(ret, 0, sizeof(xmlSchemaFacet));
1996
1997 return (ret);
1998}
1999
2000/**
2001 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002002 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002003 * @node: a node
2004 *
2005 * Allocate a new annotation structure.
2006 *
2007 * Returns the newly allocated structure or NULL in case or error
2008 */
2009static xmlSchemaAnnotPtr
2010xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2011{
2012 xmlSchemaAnnotPtr ret;
2013
2014 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2015 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002016 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002017 return (NULL);
2018 }
2019 memset(ret, 0, sizeof(xmlSchemaAnnot));
2020 ret->content = node;
2021 return (ret);
2022}
2023
2024/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002025 * xmlSchemaFreeAnnot:
2026 * @annot: a schema type structure
2027 *
2028 * Deallocate a annotation structure
2029 */
2030static void
2031xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2032{
2033 if (annot == NULL)
2034 return;
2035 xmlFree(annot);
2036}
2037
2038/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002039 * xmlSchemaFreeImport:
2040 * @import: a schema import structure
2041 *
2042 * Deallocate an import structure
2043 */
2044static void
2045xmlSchemaFreeImport(xmlSchemaImportPtr import)
2046{
2047 if (import == NULL)
2048 return;
2049
2050 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002051 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002052 xmlFree(import);
2053}
2054
2055/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002056 * xmlSchemaFreeInclude:
2057 * @include: a schema include structure
2058 *
2059 * Deallocate an include structure
2060 */
2061static void
2062xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2063{
2064 if (include == NULL)
2065 return;
2066
2067 xmlFreeDoc(include->doc);
2068 xmlFree(include);
2069}
2070
2071/**
2072 * xmlSchemaFreeIncludeList:
2073 * @includes: a schema include list
2074 *
2075 * Deallocate an include structure
2076 */
2077static void
2078xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2079{
2080 xmlSchemaIncludePtr next;
2081
2082 while (includes != NULL) {
2083 next = includes->next;
2084 xmlSchemaFreeInclude(includes);
2085 includes = next;
2086 }
2087}
2088
2089/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002090 * xmlSchemaFreeNotation:
2091 * @schema: a schema notation structure
2092 *
2093 * Deallocate a Schema Notation structure.
2094 */
2095static void
2096xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2097{
2098 if (nota == NULL)
2099 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002100 xmlFree(nota);
2101}
2102
2103/**
2104 * xmlSchemaFreeAttribute:
2105 * @schema: a schema attribute structure
2106 *
2107 * Deallocate a Schema Attribute structure.
2108 */
2109static void
2110xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2111{
2112 if (attr == NULL)
2113 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002114 if (attr->annot != NULL)
2115 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002116 if (attr->defVal != NULL)
2117 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002118 xmlFree(attr);
2119}
2120
2121/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002122 * xmlSchemaFreeWildcardNsSet:
2123 * set: a schema wildcard namespace
2124 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002125 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002126 */
2127static void
2128xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2129{
2130 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002131
Daniel Veillard3646d642004-06-02 19:19:14 +00002132 while (set != NULL) {
2133 next = set->next;
2134 xmlFree(set);
2135 set = next;
2136 }
2137}
2138
2139/**
2140 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002141 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002142 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002143 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002144 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002145void
Daniel Veillard3646d642004-06-02 19:19:14 +00002146xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2147{
2148 if (wildcard == NULL)
2149 return;
2150 if (wildcard->annot != NULL)
2151 xmlSchemaFreeAnnot(wildcard->annot);
2152 if (wildcard->nsSet != NULL)
2153 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2154 if (wildcard->negNsSet != NULL)
2155 xmlFree(wildcard->negNsSet);
2156 xmlFree(wildcard);
2157}
2158
2159/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002160 * xmlSchemaFreeAttributeGroup:
2161 * @schema: a schema attribute group structure
2162 *
2163 * Deallocate a Schema Attribute Group structure.
2164 */
2165static void
2166xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2167{
2168 if (attr == NULL)
2169 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002170 if (attr->annot != NULL)
2171 xmlSchemaFreeAnnot(attr->annot);
2172 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2173 (attr->attributeWildcard != NULL))
2174 xmlSchemaFreeWildcard(attr->attributeWildcard);
2175
Daniel Veillard4255d502002-04-16 15:50:10 +00002176 xmlFree(attr);
2177}
2178
2179/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002180 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002181 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002182 *
2183 * Deallocate a list of schema attribute uses.
2184 */
2185static void
2186xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2187{
2188 xmlSchemaAttributeLinkPtr next;
2189
2190 while (attrUse != NULL) {
2191 next = attrUse->next;
2192 xmlFree(attrUse);
2193 attrUse = next;
2194 }
2195}
2196
2197/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002198 * xmlSchemaFreeTypeLinkList:
2199 * @alink: a type link
2200 *
2201 * Deallocate a list of types.
2202 */
2203static void
2204xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2205{
2206 xmlSchemaTypeLinkPtr next;
2207
2208 while (link != NULL) {
2209 next = link->next;
2210 xmlFree(link);
2211 link = next;
2212 }
2213}
2214
2215/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002216 * xmlSchemaFreeElement:
2217 * @schema: a schema element structure
2218 *
2219 * Deallocate a Schema Element structure.
2220 */
2221static void
2222xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2223{
2224 if (elem == NULL)
2225 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002226 if (elem->annot != NULL)
2227 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002228 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002229 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002230 if (elem->defVal != NULL)
2231 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002232 xmlFree(elem);
2233}
2234
2235/**
2236 * xmlSchemaFreeFacet:
2237 * @facet: a schema facet structure
2238 *
2239 * Deallocate a Schema Facet structure.
2240 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002241void
Daniel Veillard4255d502002-04-16 15:50:10 +00002242xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2243{
2244 if (facet == NULL)
2245 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002247 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002248 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002249 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002250 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002251 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002252 xmlFree(facet);
2253}
2254
2255/**
2256 * xmlSchemaFreeType:
2257 * @type: a schema type structure
2258 *
2259 * Deallocate a Schema Type structure.
2260 */
2261void
2262xmlSchemaFreeType(xmlSchemaTypePtr type)
2263{
2264 if (type == NULL)
2265 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002266 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002267 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002268 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002269 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002270
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002271 facet = type->facets;
2272 while (facet != NULL) {
2273 next = facet->next;
2274 xmlSchemaFreeFacet(facet);
2275 facet = next;
2276 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002277 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002278 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2279 if (type->attributeUses != NULL)
2280 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002281 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002282 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002283 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2284 /*
2285 * NOTE: The only case where an attribute wildcard
2286 * is not owned, is if a complex type inherits it
2287 * from a base type.
2288 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002289 xmlSchemaFreeWildcard(type->attributeWildcard);
2290 }
2291 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002292 if (type->memberTypes != NULL)
2293 xmlSchemaFreeTypeLinkList(type->memberTypes);
2294 if (type->facetSet != NULL) {
2295 xmlSchemaFacetLinkPtr next, link;
2296
2297 link = type->facetSet;
2298 do {
2299 next = link->next;
2300 xmlFree(link);
2301 link = next;
2302 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002303 }
2304 if (type->contModel != NULL)
2305 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002306 xmlFree(type);
2307}
2308
2309/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002310 * xmlSchemaFreeTypeList:
2311 * @type: a schema type structure
2312 *
2313 * Deallocate a Schema Type structure.
2314 */
2315static void
2316xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2317{
2318 xmlSchemaTypePtr next;
2319
2320 while (type != NULL) {
2321 next = type->redef;
2322 xmlSchemaFreeType(type);
2323 type = next;
2324 }
2325}
2326
2327/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002328 * xmlSchemaFree:
2329 * @schema: a schema structure
2330 *
2331 * Deallocate a Schema structure.
2332 */
2333void
2334xmlSchemaFree(xmlSchemaPtr schema)
2335{
2336 if (schema == NULL)
2337 return;
2338
Daniel Veillard4255d502002-04-16 15:50:10 +00002339 if (schema->notaDecl != NULL)
2340 xmlHashFree(schema->notaDecl,
2341 (xmlHashDeallocator) xmlSchemaFreeNotation);
2342 if (schema->attrDecl != NULL)
2343 xmlHashFree(schema->attrDecl,
2344 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2345 if (schema->attrgrpDecl != NULL)
2346 xmlHashFree(schema->attrgrpDecl,
2347 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2348 if (schema->elemDecl != NULL)
2349 xmlHashFree(schema->elemDecl,
2350 (xmlHashDeallocator) xmlSchemaFreeElement);
2351 if (schema->typeDecl != NULL)
2352 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002353 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002354 if (schema->groupDecl != NULL)
2355 xmlHashFree(schema->groupDecl,
2356 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002357 if (schema->schemasImports != NULL)
2358 xmlHashFree(schema->schemasImports,
2359 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002360 if (schema->includes != NULL) {
2361 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2362 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002363 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002364 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002365 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002366 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002367 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002368 xmlFree(schema);
2369}
2370
2371/************************************************************************
2372 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002373 * Debug functions *
2374 * *
2375 ************************************************************************/
2376
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002377#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002378
Daniel Veillard4255d502002-04-16 15:50:10 +00002379/**
2380 * xmlSchemaElementDump:
2381 * @elem: an element
2382 * @output: the file output
2383 *
2384 * Dump the element
2385 */
2386static void
2387xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002388 const xmlChar * name ATTRIBUTE_UNUSED,
2389 const xmlChar * context ATTRIBUTE_UNUSED,
2390 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002391{
2392 if (elem == NULL)
2393 return;
2394
2395 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002396 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2397 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002398 fprintf(output, ": %s ", elem->name);
2399 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002400 fprintf(output, "namespace '%s' ", namespace);
2401
Daniel Veillard4255d502002-04-16 15:50:10 +00002402 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002403 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002404 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002405 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002406 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002407 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002408 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002409 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002410 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002411 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002412 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002413 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002414 fprintf(output, "\n");
2415 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002416 fprintf(output, " ");
2417 if (elem->minOccurs != 1)
2418 fprintf(output, "min: %d ", elem->minOccurs);
2419 if (elem->maxOccurs >= UNBOUNDED)
2420 fprintf(output, "max: unbounded\n");
2421 else if (elem->maxOccurs != 1)
2422 fprintf(output, "max: %d\n", elem->maxOccurs);
2423 else
2424 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002425 }
2426 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002427 fprintf(output, " type: %s", elem->namedType);
2428 if (elem->namedTypeNs != NULL)
2429 fprintf(output, " ns %s\n", elem->namedTypeNs);
2430 else
2431 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002432 }
2433 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002434 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2435 if (elem->substGroupNs != NULL)
2436 fprintf(output, " ns %s\n", elem->substGroupNs);
2437 else
2438 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002439 }
2440 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002441 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002442}
2443
2444/**
2445 * xmlSchemaAnnotDump:
2446 * @output: the file output
2447 * @annot: a annotation
2448 *
2449 * Dump the annotation
2450 */
2451static void
2452xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2453{
2454 xmlChar *content;
2455
2456 if (annot == NULL)
2457 return;
2458
2459 content = xmlNodeGetContent(annot->content);
2460 if (content != NULL) {
2461 fprintf(output, " Annot: %s\n", content);
2462 xmlFree(content);
2463 } else
2464 fprintf(output, " Annot: empty\n");
2465}
2466
2467/**
2468 * xmlSchemaTypeDump:
2469 * @output: the file output
2470 * @type: a type structure
2471 *
2472 * Dump a SchemaType structure
2473 */
2474static void
2475xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2476{
2477 if (type == NULL) {
2478 fprintf(output, "Type: NULL\n");
2479 return;
2480 }
2481 fprintf(output, "Type: ");
2482 if (type->name != NULL)
2483 fprintf(output, "%s, ", type->name);
2484 else
2485 fprintf(output, "no name");
2486 switch (type->type) {
2487 case XML_SCHEMA_TYPE_BASIC:
2488 fprintf(output, "basic ");
2489 break;
2490 case XML_SCHEMA_TYPE_SIMPLE:
2491 fprintf(output, "simple ");
2492 break;
2493 case XML_SCHEMA_TYPE_COMPLEX:
2494 fprintf(output, "complex ");
2495 break;
2496 case XML_SCHEMA_TYPE_SEQUENCE:
2497 fprintf(output, "sequence ");
2498 break;
2499 case XML_SCHEMA_TYPE_CHOICE:
2500 fprintf(output, "choice ");
2501 break;
2502 case XML_SCHEMA_TYPE_ALL:
2503 fprintf(output, "all ");
2504 break;
2505 case XML_SCHEMA_TYPE_UR:
2506 fprintf(output, "ur ");
2507 break;
2508 case XML_SCHEMA_TYPE_RESTRICTION:
2509 fprintf(output, "restriction ");
2510 break;
2511 case XML_SCHEMA_TYPE_EXTENSION:
2512 fprintf(output, "extension ");
2513 break;
2514 default:
2515 fprintf(output, "unknowntype%d ", type->type);
2516 break;
2517 }
2518 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002519 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002520 }
2521 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002522 case XML_SCHEMA_CONTENT_UNKNOWN:
2523 fprintf(output, "unknown ");
2524 break;
2525 case XML_SCHEMA_CONTENT_EMPTY:
2526 fprintf(output, "empty ");
2527 break;
2528 case XML_SCHEMA_CONTENT_ELEMENTS:
2529 fprintf(output, "element ");
2530 break;
2531 case XML_SCHEMA_CONTENT_MIXED:
2532 fprintf(output, "mixed ");
2533 break;
2534 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002535 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002536 break;
2537 case XML_SCHEMA_CONTENT_BASIC:
2538 fprintf(output, "basic ");
2539 break;
2540 case XML_SCHEMA_CONTENT_SIMPLE:
2541 fprintf(output, "simple ");
2542 break;
2543 case XML_SCHEMA_CONTENT_ANY:
2544 fprintf(output, "any ");
2545 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002546 }
2547 fprintf(output, "\n");
2548 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002549 fprintf(output, " ");
2550 if (type->minOccurs != 1)
2551 fprintf(output, "min: %d ", type->minOccurs);
2552 if (type->maxOccurs >= UNBOUNDED)
2553 fprintf(output, "max: unbounded\n");
2554 else if (type->maxOccurs != 1)
2555 fprintf(output, "max: %d\n", type->maxOccurs);
2556 else
2557 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002558 }
2559 if (type->annot != NULL)
2560 xmlSchemaAnnotDump(output, type->annot);
2561 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002562 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002563
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002564 fprintf(output, " subtypes: ");
2565 while (sub != NULL) {
2566 fprintf(output, "%s ", sub->name);
2567 sub = sub->next;
2568 }
2569 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002570 }
2571
2572}
2573
2574/**
2575 * xmlSchemaDump:
2576 * @output: the file output
2577 * @schema: a schema structure
2578 *
2579 * Dump a Schema structure.
2580 */
2581void
2582xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2583{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002584 if (output == NULL)
2585 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002586 if (schema == NULL) {
2587 fprintf(output, "Schemas: NULL\n");
2588 return;
2589 }
2590 fprintf(output, "Schemas: ");
2591 if (schema->name != NULL)
2592 fprintf(output, "%s, ", schema->name);
2593 else
2594 fprintf(output, "no name, ");
2595 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002596 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002597 else
2598 fprintf(output, "no target namespace");
2599 fprintf(output, "\n");
2600 if (schema->annot != NULL)
2601 xmlSchemaAnnotDump(output, schema->annot);
2602
2603 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2604 output);
2605 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002606 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002607}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002608#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002609
2610/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002611 * *
2612 * Utilities *
2613 * *
2614 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002615
Daniel Veillardc0826a72004-08-10 14:17:33 +00002616/**
2617 * xmlSchemaGetPropNode:
2618 * @node: the element node
2619 * @name: the name of the attribute
2620 *
2621 * Seeks an attribute with a name of @name in
2622 * no namespace.
2623 *
2624 * Returns the attribute or NULL if not present.
2625 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002626static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002627xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002628{
2629 xmlAttrPtr prop;
2630
Daniel Veillardc0826a72004-08-10 14:17:33 +00002631 if ((node == NULL) || (name == NULL))
2632 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002633 prop = node->properties;
2634 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002635 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2636 return(prop);
2637 prop = prop->next;
2638 }
2639 return (NULL);
2640}
2641
2642/**
2643 * xmlSchemaGetPropNodeNs:
2644 * @node: the element node
2645 * @uri: the uri
2646 * @name: the name of the attribute
2647 *
2648 * Seeks an attribute with a local name of @name and
2649 * a namespace URI of @uri.
2650 *
2651 * Returns the attribute or NULL if not present.
2652 */
2653static xmlAttrPtr
2654xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2655{
2656 xmlAttrPtr prop;
2657
2658 if ((node == NULL) || (name == NULL))
2659 return(NULL);
2660 prop = node->properties;
2661 while (prop != NULL) {
2662 if ((prop->ns != NULL) &&
2663 xmlStrEqual(prop->name, BAD_CAST name) &&
2664 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002665 return(prop);
2666 prop = prop->next;
2667 }
2668 return (NULL);
2669}
2670
2671static const xmlChar *
2672xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2673{
2674 xmlChar *val;
2675 const xmlChar *ret;
2676
2677 val = xmlNodeGetContent(node);
2678 if (val == NULL)
2679 return(NULL);
2680 ret = xmlDictLookup(ctxt->dict, val, -1);
2681 xmlFree(val);
2682 return(ret);
2683}
2684
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002685/**
2686 * xmlSchemaGetProp:
2687 * @ctxt: the parser context
2688 * @node: the node
2689 * @name: the property name
2690 *
2691 * Read a attribute value and internalize the string
2692 *
2693 * Returns the string or NULL if not present.
2694 */
2695static const xmlChar *
2696xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2697 const char *name)
2698{
2699 xmlChar *val;
2700 const xmlChar *ret;
2701
2702 val = xmlGetProp(node, BAD_CAST name);
2703 if (val == NULL)
2704 return(NULL);
2705 ret = xmlDictLookup(ctxt->dict, val, -1);
2706 xmlFree(val);
2707 return(ret);
2708}
2709
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002710/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002711 * *
2712 * Parsing functions *
2713 * *
2714 ************************************************************************/
2715
2716/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002717 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002718 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002719 * @name: the element name
2720 * @ns: the element namespace
2721 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002722 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002723 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002724 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002725 */
2726static xmlSchemaElementPtr
2727xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002728 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002729{
2730 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002731
2732 if ((name == NULL) || (schema == NULL))
2733 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002734
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002735 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002736 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002737 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002738 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002739 } else
2740 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002741 /*
2742 * This one was removed, since top level element declarations have
2743 * the target namespace specified in targetNamespace of the <schema>
2744 * information element, even if elementFormDefault is "unqualified".
2745 */
2746
2747 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002748 if (xmlStrEqual(namespace, schema->targetNamespace))
2749 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2750 else
2751 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002752 if ((ret != NULL) &&
2753 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002754 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002755 }
William M. Bracke7091952004-05-11 15:09:58 +00002756 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002757
William M. Brack2f2a6632004-08-20 23:09:47 +00002758 /*
2759 * Removed since imported components will be hold by the main schema only.
2760 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002761 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002762 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002763 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002764 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002765 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002766 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002767 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2768 return (ret);
2769 } else
2770 ret = NULL;
2771 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002772 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002773#ifdef DEBUG
2774 if (ret == NULL) {
2775 if (namespace == NULL)
2776 fprintf(stderr, "Unable to lookup type %s", name);
2777 else
2778 fprintf(stderr, "Unable to lookup type %s:%s", name,
2779 namespace);
2780 }
2781#endif
2782 return (ret);
2783}
2784
2785/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002786 * xmlSchemaGetType:
2787 * @schema: the schemas context
2788 * @name: the type name
2789 * @ns: the type namespace
2790 *
2791 * Lookup a type in the schemas or the predefined types
2792 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002793 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002794 */
2795static xmlSchemaTypePtr
2796xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002797 const xmlChar * namespace)
2798{
Daniel Veillard4255d502002-04-16 15:50:10 +00002799 xmlSchemaTypePtr ret;
2800
2801 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002802 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002803 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002804 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002805 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002806 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002807 }
2808 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002809 if (ret != NULL)
2810 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002811 /*
2812 * Removed, since the imported components will be grafted on the
2813 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002814 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002815 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002816 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002817 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002818 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002819 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002820 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2821 return (ret);
2822 } else
2823 ret = NULL;
2824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002825 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002826#ifdef DEBUG
2827 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002828 if (namespace == NULL)
2829 fprintf(stderr, "Unable to lookup type %s", name);
2830 else
2831 fprintf(stderr, "Unable to lookup type %s:%s", name,
2832 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 }
2834#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002835 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002836}
2837
Daniel Veillard3646d642004-06-02 19:19:14 +00002838/**
2839 * xmlSchemaGetAttribute:
2840 * @schema: the context of the schema
2841 * @name: the name of the attribute
2842 * @ns: the target namespace of the attribute
2843 *
2844 * Lookup a an attribute in the schema or imported schemas
2845 *
2846 * Returns the attribute declaration or NULL if not found.
2847 */
2848static xmlSchemaAttributePtr
2849xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2850 const xmlChar * namespace)
2851{
2852 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002853
2854 if ((name == NULL) || (schema == NULL))
2855 return (NULL);
2856
2857
2858 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2859 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2860 return (ret);
2861 else
2862 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002863 /*
2864 * Removed, since imported components will be hold by the main schema only.
2865 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002866 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002867 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002868 else
2869 import = xmlHashLookup(schema->schemasImports, namespace);
2870 if (import != NULL) {
2871 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2872 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2873 return (ret);
2874 } else
2875 ret = NULL;
2876 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002877 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002878#ifdef DEBUG
2879 if (ret == NULL) {
2880 if (namespace == NULL)
2881 fprintf(stderr, "Unable to lookup attribute %s", name);
2882 else
2883 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2884 namespace);
2885 }
2886#endif
2887 return (ret);
2888}
2889
2890/**
2891 * xmlSchemaGetAttributeGroup:
2892 * @schema: the context of the schema
2893 * @name: the name of the attribute group
2894 * @ns: the target namespace of the attribute group
2895 *
2896 * Lookup a an attribute group in the schema or imported schemas
2897 *
2898 * Returns the attribute group definition or NULL if not found.
2899 */
2900static xmlSchemaAttributeGroupPtr
2901xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2902 const xmlChar * namespace)
2903{
2904 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002905
2906 if ((name == NULL) || (schema == NULL))
2907 return (NULL);
2908
2909
2910 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2911 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2912 return (ret);
2913 else
2914 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002915 /*
2916 * Removed since imported components will be hold by the main schema only.
2917 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002918 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002919 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002920 else
2921 import = xmlHashLookup(schema->schemasImports, namespace);
2922 if (import != NULL) {
2923 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2924 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2925 return (ret);
2926 else
2927 ret = NULL;
2928 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002929 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002930#ifdef DEBUG
2931 if (ret == NULL) {
2932 if (namespace == NULL)
2933 fprintf(stderr, "Unable to lookup attribute group %s", name);
2934 else
2935 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2936 namespace);
2937 }
2938#endif
2939 return (ret);
2940}
2941
2942/**
2943 * xmlSchemaGetGroup:
2944 * @schema: the context of the schema
2945 * @name: the name of the group
2946 * @ns: the target namespace of the group
2947 *
2948 * Lookup a group in the schema or imported schemas
2949 *
2950 * Returns the group definition or NULL if not found.
2951 */
2952static xmlSchemaTypePtr
2953xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2954 const xmlChar * namespace)
2955{
2956 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002957
2958 if ((name == NULL) || (schema == NULL))
2959 return (NULL);
2960
2961
2962 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2963 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2964 return (ret);
2965 else
2966 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002967 /*
2968 * Removed since imported components will be hold by the main schema only.
2969 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002970 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002971 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002972 else
2973 import = xmlHashLookup(schema->schemasImports, namespace);
2974 if (import != NULL) {
2975 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2976 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2977 return (ret);
2978 else
2979 ret = NULL;
2980 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002981 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002982#ifdef DEBUG
2983 if (ret == NULL) {
2984 if (namespace == NULL)
2985 fprintf(stderr, "Unable to lookup group %s", name);
2986 else
2987 fprintf(stderr, "Unable to lookup group %s:%s", name,
2988 namespace);
2989 }
2990#endif
2991 return (ret);
2992}
2993
Daniel Veillard4255d502002-04-16 15:50:10 +00002994/************************************************************************
2995 * *
2996 * Parsing functions *
2997 * *
2998 ************************************************************************/
2999
3000#define IS_BLANK_NODE(n) \
3001 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3002
3003/**
3004 * xmlSchemaIsBlank:
3005 * @str: a string
3006 *
3007 * Check if a string is ignorable
3008 *
3009 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3010 */
3011static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003012xmlSchemaIsBlank(xmlChar * str)
3013{
Daniel Veillard4255d502002-04-16 15:50:10 +00003014 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003015 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003017 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003018 return (0);
3019 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003020 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003021 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003022}
3023
3024/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003025 * xmlSchemaAddAssembledItem:
3026 * @ctxt: a schema parser context
3027 * @schema: the schema being built
3028 * @item: the item
3029 *
3030 * Add a item to the schema's list of current items.
3031 * This is used if the schema was already constructed and
3032 * new schemata need to be added to it.
3033 * *WARNING* this interface is highly subject to change.
3034 *
3035 * Returns 0 if suceeds and -1 if an internal error occurs.
3036 */
3037static int
3038xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3039 xmlSchemaTypePtr item)
3040{
3041 static int growSize = 100;
3042 xmlSchemaAssemblePtr ass;
3043
3044 ass = ctxt->assemble;
3045 if (ass->sizeItems < 0) {
3046 /* If disabled. */
3047 return (0);
3048 }
3049 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003050 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003051 if (ass->items == NULL) {
3052 xmlSchemaPErrMemory(ctxt,
3053 "allocating new item buffer", NULL);
3054 return (-1);
3055 }
3056 ass->sizeItems = growSize;
3057 } else if (ass->sizeItems <= ass->nbItems) {
3058 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003059 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003060 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3061 if (ass->items == NULL) {
3062 xmlSchemaPErrMemory(ctxt,
3063 "growing item buffer", NULL);
3064 ass->sizeItems = 0;
3065 return (-1);
3066 }
3067 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003068 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003069 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3070 return (0);
3071}
3072
3073/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003074 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003075 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003076 * @schema: the schema being built
3077 * @name: the item name
3078 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003079 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003080 * *WARNING* this interface is highly subject to change
3081 *
3082 * Returns the new struture or NULL in case of error
3083 */
3084static xmlSchemaNotationPtr
3085xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003086 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003087{
3088 xmlSchemaNotationPtr ret = NULL;
3089 int val;
3090
3091 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3092 return (NULL);
3093
3094 if (schema->notaDecl == NULL)
3095 schema->notaDecl = xmlHashCreate(10);
3096 if (schema->notaDecl == NULL)
3097 return (NULL);
3098
3099 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3100 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003101 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003102 return (NULL);
3103 }
3104 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003105 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003106 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3107 ret);
3108 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003109 /*
3110 * TODO: This should never happen, since a unique name will be computed.
3111 * If it fails, then an other internal error must have occured.
3112 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003113 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3114 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003115 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003116 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003117 xmlFree(ret);
3118 return (NULL);
3119 }
3120 return (ret);
3121}
3122
3123
3124/**
3125 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003126 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003127 * @schema: the schema being built
3128 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003129 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003130 *
3131 * Add an XML schema Attrribute declaration
3132 * *WARNING* this interface is highly subject to change
3133 *
3134 * Returns the new struture or NULL in case of error
3135 */
3136static xmlSchemaAttributePtr
3137xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003138 const xmlChar * name, const xmlChar * namespace,
3139 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003140{
3141 xmlSchemaAttributePtr ret = NULL;
3142 int val;
3143
3144 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3145 return (NULL);
3146
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003147#ifdef DEBUG
3148 fprintf(stderr, "Adding attribute %s\n", name);
3149 if (namespace != NULL)
3150 fprintf(stderr, " target namespace %s\n", namespace);
3151#endif
3152
Daniel Veillard4255d502002-04-16 15:50:10 +00003153 if (schema->attrDecl == NULL)
3154 schema->attrDecl = xmlHashCreate(10);
3155 if (schema->attrDecl == NULL)
3156 return (NULL);
3157
3158 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3159 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003160 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003161 return (NULL);
3162 }
3163 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003164 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3165 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003166 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003167 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003168 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003169 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003170 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003171 NULL, NULL, node,
3172 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003173 xmlFree(ret);
3174 return (NULL);
3175 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003176 if (ctxt->assemble != NULL)
3177 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003178 return (ret);
3179}
3180
3181/**
3182 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003183 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003184 * @schema: the schema being built
3185 * @name: the item name
3186 *
3187 * Add an XML schema Attrribute Group declaration
3188 *
3189 * Returns the new struture or NULL in case of error
3190 */
3191static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003192xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003193 xmlSchemaPtr schema, const xmlChar * name,
3194 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003195{
3196 xmlSchemaAttributeGroupPtr ret = NULL;
3197 int val;
3198
3199 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3200 return (NULL);
3201
3202 if (schema->attrgrpDecl == NULL)
3203 schema->attrgrpDecl = xmlHashCreate(10);
3204 if (schema->attrgrpDecl == NULL)
3205 return (NULL);
3206
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003207 ret =
3208 (xmlSchemaAttributeGroupPtr)
3209 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003212 return (NULL);
3213 }
3214 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003215 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003216 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003217 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003219 xmlSchemaPCustomErr(ctxt,
3220 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3221 NULL, NULL, node,
3222 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003223 xmlFree(ret);
3224 return (NULL);
3225 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003226 if (ctxt->assemble != NULL)
3227 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003228 return (ret);
3229}
3230
3231/**
3232 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003233 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003234 * @schema: the schema being built
3235 * @name: the type name
3236 * @namespace: the type namespace
3237 *
3238 * Add an XML schema Element declaration
3239 * *WARNING* this interface is highly subject to change
3240 *
3241 * Returns the new struture or NULL in case of error
3242 */
3243static xmlSchemaElementPtr
3244xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003245 const xmlChar * name, const xmlChar * namespace,
3246 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003247{
3248 xmlSchemaElementPtr ret = NULL;
3249 int val;
3250
3251 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3252 return (NULL);
3253
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003254#ifdef DEBUG
3255 fprintf(stderr, "Adding element %s\n", name);
3256 if (namespace != NULL)
3257 fprintf(stderr, " target namespace %s\n", namespace);
3258#endif
3259
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 if (schema->elemDecl == NULL)
3261 schema->elemDecl = xmlHashCreate(10);
3262 if (schema->elemDecl == NULL)
3263 return (NULL);
3264
3265 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3266 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003267 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003268 return (NULL);
3269 }
3270 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003271 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3272 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003273 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003274 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003275 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003276 if (topLevel) {
3277 xmlSchemaPCustomErr(ctxt,
3278 XML_SCHEMAP_REDEFINED_ELEMENT,
3279 NULL, NULL, node,
3280 "A global element declaration with the name '%s' does "
3281 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003282 xmlFree(ret);
3283 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003284 } else {
3285 char buf[30];
3286
3287 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3288 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3289 namespace, ret);
3290 if (val != 0) {
3291 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003292 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003293 NULL, NULL, node,
3294 "Internal error: xmlSchemaAddElement, "
3295 "a dublicate element declaration with the name '%s' "
3296 "could not be added to the hash.", name);
3297 xmlFree(ret);
3298 return (NULL);
3299 }
3300 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003301
Daniel Veillard4255d502002-04-16 15:50:10 +00003302 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003303 if (ctxt->assemble != NULL)
3304 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003305 return (ret);
3306}
3307
3308/**
3309 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003310 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003311 * @schema: the schema being built
3312 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003313 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003314 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003315 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003316 * *WARNING* this interface is highly subject to change
3317 *
3318 * Returns the new struture or NULL in case of error
3319 */
3320static xmlSchemaTypePtr
3321xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003322 const xmlChar * name, const xmlChar * namespace,
3323 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003324{
3325 xmlSchemaTypePtr ret = NULL;
3326 int val;
3327
3328 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3329 return (NULL);
3330
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003331#ifdef DEBUG
3332 fprintf(stderr, "Adding type %s\n", name);
3333 if (namespace != NULL)
3334 fprintf(stderr, " target namespace %s\n", namespace);
3335#endif
3336
Daniel Veillard4255d502002-04-16 15:50:10 +00003337 if (schema->typeDecl == NULL)
3338 schema->typeDecl = xmlHashCreate(10);
3339 if (schema->typeDecl == NULL)
3340 return (NULL);
3341
3342 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3343 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003344 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003345 return (NULL);
3346 }
3347 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003348 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003349 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003350 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003351 if (val != 0) {
3352 if (ctxt->includes == 0) {
3353 xmlSchemaPCustomErr(ctxt,
3354 XML_SCHEMAP_REDEFINED_TYPE,
3355 NULL, NULL, node,
3356 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003357 xmlFree(ret);
3358 return (NULL);
3359 } else {
3360 xmlSchemaTypePtr prev;
3361
3362 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3363 if (prev == NULL) {
3364 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003365 XML_ERR_INTERNAL_ERROR,
3366 "Internal error: xmlSchemaAddType, on type "
3367 "'%s'.\n",
3368 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003369 xmlFree(ret);
3370 return (NULL);
3371 }
3372 ret->redef = prev->redef;
3373 prev->redef = ret;
3374 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003375 }
3376 ret->minOccurs = 1;
3377 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003378 ret->attributeUses = NULL;
3379 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003380 if (ctxt->assemble != NULL)
3381 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003382 return (ret);
3383}
3384
3385/**
3386 * xmlSchemaAddGroup:
3387 * @ctxt: a schema validation context
3388 * @schema: the schema being built
3389 * @name: the group name
3390 *
3391 * Add an XML schema Group definition
3392 *
3393 * Returns the new struture or NULL in case of error
3394 */
3395static xmlSchemaTypePtr
3396xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003397 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003398{
3399 xmlSchemaTypePtr ret = NULL;
3400 int val;
3401
3402 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3403 return (NULL);
3404
3405 if (schema->groupDecl == NULL)
3406 schema->groupDecl = xmlHashCreate(10);
3407 if (schema->groupDecl == NULL)
3408 return (NULL);
3409
3410 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3411 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003413 return (NULL);
3414 }
3415 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003416 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003417 val =
3418 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3419 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003420 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003421 xmlSchemaPCustomErr(ctxt,
3422 XML_SCHEMAP_REDEFINED_GROUP,
3423 NULL, NULL, node,
3424 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003425 xmlFree(ret);
3426 return (NULL);
3427 }
3428 ret->minOccurs = 1;
3429 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003430 if (ctxt->assemble != NULL)
3431 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003432 return (ret);
3433}
3434
Daniel Veillard3646d642004-06-02 19:19:14 +00003435/**
3436 * xmlSchemaNewWildcardNs:
3437 * @ctxt: a schema validation context
3438 *
3439 * Creates a new wildcard namespace constraint.
3440 *
3441 * Returns the new struture or NULL in case of error
3442 */
3443static xmlSchemaWildcardNsPtr
3444xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3445{
3446 xmlSchemaWildcardNsPtr ret;
3447
3448 ret = (xmlSchemaWildcardNsPtr)
3449 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3450 if (ret == NULL) {
3451 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3452 return (NULL);
3453 }
3454 ret->value = NULL;
3455 ret->next = NULL;
3456 return (ret);
3457}
3458
3459/**
3460 * xmlSchemaAddWildcard:
3461 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003462 * Adds a wildcard. It corresponds to a
3463 * xsd:anyAttribute and is used as storage for namespace
3464 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003465 *
3466 * Returns the new struture or NULL in case of error
3467 */
3468static xmlSchemaWildcardPtr
3469xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3470{
3471 xmlSchemaWildcardPtr ret = NULL;
3472
3473 if (ctxt == NULL)
3474 return (NULL);
3475
3476 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3477 if (ret == NULL) {
3478 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3479 return (NULL);
3480 }
3481 memset(ret, 0, sizeof(xmlSchemaWildcard));
3482 ret->minOccurs = 1;
3483 ret->maxOccurs = 1;
3484
3485 return (ret);
3486}
3487
Daniel Veillard4255d502002-04-16 15:50:10 +00003488/************************************************************************
3489 * *
3490 * Utilities for parsing *
3491 * *
3492 ************************************************************************/
3493
3494/**
3495 * xmlGetQNameProp:
3496 * @ctxt: a schema validation context
3497 * @node: a subtree containing XML Schema informations
3498 * @name: the attribute name
3499 * @namespace: the result namespace if any
3500 *
3501 * Extract a QName Attribute value
3502 *
3503 * Returns the NCName or NULL if not found, and also update @namespace
3504 * with the namespace URI
3505 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003506static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003507xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003508 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003509{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003510 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003511 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003512 const xmlChar *ret, *prefix;
3513 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003514 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003515
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003516 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003517 attr = xmlSchemaGetPropNode(node, name);
3518 if (attr == NULL)
3519 return (NULL);
3520 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003521
Daniel Veillard4255d502002-04-16 15:50:10 +00003522 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003523 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003524
Daniel Veillardba0153a2004-04-01 10:42:31 +00003525 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003526 ns = xmlSearchNs(node->doc, node, 0);
3527 if (ns) {
3528 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3529 return (val);
3530 }
3531 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003532 ret = xmlSplitQName3(val, &len);
3533 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003534 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003535 }
3536 ret = xmlDictLookup(ctxt->dict, ret, -1);
3537 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003538
3539 ns = xmlSearchNs(node->doc, node, prefix);
3540 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003541 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3542 NULL, NULL, (xmlNodePtr) attr,
3543 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003544 "The QName value '%s' has no corresponding namespace "
3545 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003546 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003547 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003548 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003549 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003550}
3551
3552/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003553 * xmlSchemaPValAttrNodeQNameValue:
3554 * @ctxt: a schema parser context
3555 * @schema: the schema context
3556 * @ownerDes: the designation of the parent element
3557 * @ownerItem: the parent as a schema object
3558 * @value: the QName value
3559 * @local: the resulting local part if found, the attribute value otherwise
3560 * @uri: the resulting namespace URI if found
3561 *
3562 * Extracts the local name and the URI of a QName value and validates it.
3563 * This one is intended to be used on attribute values that
3564 * should resolve to schema components.
3565 *
3566 * Returns 0, in case the QName is valid, a positive error code
3567 * if not valid and -1 if an internal error occurs.
3568 */
3569static int
3570xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3571 xmlSchemaPtr schema,
3572 xmlChar **ownerDes,
3573 xmlSchemaTypePtr ownerItem,
3574 xmlAttrPtr attr,
3575 const xmlChar *value,
3576 const xmlChar **uri,
3577 const xmlChar **prefix,
3578 const xmlChar **local)
3579{
3580 const xmlChar *pref;
3581 xmlNsPtr ns;
3582 int len, ret;
3583
3584 *uri = NULL;
3585 *local = NULL;
3586 if (prefix != 0)
3587 *prefix = NULL;
3588 ret = xmlValidateQName(value, 1);
3589 if (ret > 0) {
3590 xmlSchemaPSimpleTypeErr(ctxt,
3591 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3592 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003593 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3594 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003595 NULL, NULL, NULL);
3596 *local = value;
3597 return (ctxt->err);
3598 } else if (ret < 0)
3599 return (-1);
3600
3601 if (!strchr((char *) value, ':')) {
3602 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3603 if (ns)
3604 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3605 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3606 /*
3607 * This one takes care of included schemas with no
3608 * target namespace.
3609 */
3610 *uri = schema->targetNamespace;
3611 }
3612 *local = value;
3613 return (0);
3614 }
3615 /*
3616 * At this point xmlSplitQName3 has to return a local name.
3617 */
3618 *local = xmlSplitQName3(value, &len);
3619 *local = xmlDictLookup(ctxt->dict, *local, -1);
3620 pref = xmlDictLookup(ctxt->dict, value, len);
3621 if (prefix != 0)
3622 *prefix = pref;
3623 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3624 if (ns == NULL) {
3625 xmlSchemaPSimpleTypeErr(ctxt,
3626 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3627 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003628 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3629 "The QName value '%s' has no corresponding namespace "
3630 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003631 return (ctxt->err);
3632 } else {
3633 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3634 }
3635 return (0);
3636}
3637
3638/**
3639 * xmlSchemaPValAttrNodeQName:
3640 * @ctxt: a schema parser context
3641 * @schema: the schema context
3642 * @ownerDes: the designation of the owner element
3643 * @ownerItem: the owner as a schema object
3644 * @attr: the attribute node
3645 * @local: the resulting local part if found, the attribute value otherwise
3646 * @uri: the resulting namespace URI if found
3647 *
3648 * Extracts and validates the QName of an attribute value.
3649 * This one is intended to be used on attribute values that
3650 * should resolve to schema components.
3651 *
3652 * Returns 0, in case the QName is valid, a positive error code
3653 * if not valid and -1 if an internal error occurs.
3654 */
3655static int
3656xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3657 xmlSchemaPtr schema,
3658 xmlChar **ownerDes,
3659 xmlSchemaTypePtr ownerItem,
3660 xmlAttrPtr attr,
3661 const xmlChar **uri,
3662 const xmlChar **prefix,
3663 const xmlChar **local)
3664{
3665 const xmlChar *value;
3666
3667 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3668 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3669 ownerDes, ownerItem, attr, value, uri, prefix, local));
3670}
3671
3672/**
3673 * xmlSchemaPValAttrQName:
3674 * @ctxt: a schema parser context
3675 * @schema: the schema context
3676 * @ownerDes: the designation of the parent element
3677 * @ownerItem: the owner as a schema object
3678 * @ownerElem: the parent node of the attribute
3679 * @name: the name of the attribute
3680 * @local: the resulting local part if found, the attribute value otherwise
3681 * @uri: the resulting namespace URI if found
3682 *
3683 * Extracts and validates the QName of an attribute value.
3684 *
3685 * Returns 0, in case the QName is valid, a positive error code
3686 * if not valid and -1 if an internal error occurs.
3687 */
3688static int
3689xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3690 xmlSchemaPtr schema,
3691 xmlChar **ownerDes,
3692 xmlSchemaTypePtr ownerItem,
3693 xmlNodePtr ownerElem,
3694 const char *name,
3695 const xmlChar **uri,
3696 const xmlChar **prefix,
3697 const xmlChar **local)
3698{
3699 xmlAttrPtr attr;
3700
3701 attr = xmlSchemaGetPropNode(ownerElem, name);
3702 if (attr == NULL) {
3703 *local = NULL;
3704 *uri = NULL;
3705 return (0);
3706 }
3707 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3708 ownerDes, ownerItem, attr, uri, prefix, local));
3709}
3710
3711/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 * xmlGetMaxOccurs:
3713 * @ctxt: a schema validation context
3714 * @node: a subtree containing XML Schema informations
3715 *
3716 * Get the maxOccurs property
3717 *
3718 * Returns the default if not found, or the value
3719 */
3720static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003721xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3722 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003723{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003724 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003725 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003726 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003727
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003728 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3729 if (attr == NULL)
3730 return (def);
3731 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003732
3733 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003734 if (max != UNBOUNDED) {
3735 xmlSchemaPSimpleTypeErr(ctxt,
3736 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3737 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3738 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3739 val, NULL, NULL, NULL);
3740 return (def);
3741 } else
3742 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003743 }
3744
3745 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003746 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003747 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003748 if (*cur == 0) {
3749 xmlSchemaPSimpleTypeErr(ctxt,
3750 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3751 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3752 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3753 val, NULL, NULL, NULL);
3754 return (def);
3755 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003756 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003757 ret = ret * 10 + (*cur - '0');
3758 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003759 }
William M. Brack76e95df2003-10-18 16:20:14 +00003760 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003761 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003762 /*
3763 * TODO: Restrict the maximal value to Integer.
3764 */
3765 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3766 xmlSchemaPSimpleTypeErr(ctxt,
3767 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3768 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3769 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3770 val, NULL, NULL, NULL);
3771 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003772 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003773 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003774}
3775
3776/**
3777 * xmlGetMinOccurs:
3778 * @ctxt: a schema validation context
3779 * @node: a subtree containing XML Schema informations
3780 *
3781 * Get the minOccurs property
3782 *
3783 * Returns the default if not found, or the value
3784 */
3785static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003786xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3787 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003788{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003789 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003790 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003791 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003792
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003793 attr = xmlSchemaGetPropNode(node, "minOccurs");
3794 if (attr == NULL)
3795 return (def);
3796 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003797 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003798 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003799 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003800 if (*cur == 0) {
3801 xmlSchemaPSimpleTypeErr(ctxt,
3802 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3803 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3804 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3805 val, NULL, NULL, NULL);
3806 return (def);
3807 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003808 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003809 ret = ret * 10 + (*cur - '0');
3810 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003811 }
William M. Brack76e95df2003-10-18 16:20:14 +00003812 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003813 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003814 /*
3815 * TODO: Restrict the maximal value to Integer.
3816 */
3817 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3818 xmlSchemaPSimpleTypeErr(ctxt,
3819 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3820 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3821 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3822 val, NULL, NULL, NULL);
3823 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003824 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003825 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003826}
3827
3828/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003829 * xmlSchemaPGetBoolNodeValue:
3830 * @ctxt: a schema validation context
3831 * @ownerDes: owner designation
3832 * @ownerItem: the owner as a schema item
3833 * @node: the node holding the value
3834 *
3835 * Converts a boolean string value into 1 or 0.
3836 *
3837 * Returns 0 or 1.
3838 */
3839static int
3840xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3841 xmlChar **ownerDes,
3842 xmlSchemaTypePtr ownerItem,
3843 xmlNodePtr node)
3844{
3845 xmlChar *value = NULL;
3846 int res = 0;
3847
3848 value = xmlNodeGetContent(node);
3849 /*
3850 * 3.2.2.1 Lexical representation
3851 * An instance of a datatype that is defined as ·boolean·
3852 * can have the following legal literals {true, false, 1, 0}.
3853 */
3854 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3855 res = 1;
3856 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3857 res = 0;
3858 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3859 res = 1;
3860 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3861 res = 0;
3862 else {
3863 xmlSchemaPSimpleTypeErr(ctxt,
3864 XML_SCHEMAP_INVALID_BOOLEAN,
3865 ownerDes, ownerItem, node,
3866 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3867 "(1 | 0 | true | false)", BAD_CAST value,
3868 NULL, NULL, NULL);
3869 }
3870 if (value != NULL)
3871 xmlFree(value);
3872 return (res);
3873}
3874
3875/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003876 * xmlGetBooleanProp:
3877 * @ctxt: a schema validation context
3878 * @node: a subtree containing XML Schema informations
3879 * @name: the attribute name
3880 * @def: the default value
3881 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003882 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003883 *
3884 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003885 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 */
3887static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003888xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3889 xmlChar **ownerDes,
3890 xmlSchemaTypePtr ownerItem,
3891 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003892 const char *name, int def)
3893{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003894 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003895
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003896 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003897 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003898 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003899 /*
3900 * 3.2.2.1 Lexical representation
3901 * An instance of a datatype that is defined as ·boolean·
3902 * can have the following legal literals {true, false, 1, 0}.
3903 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003904 if (xmlStrEqual(val, BAD_CAST "true"))
3905 def = 1;
3906 else if (xmlStrEqual(val, BAD_CAST "false"))
3907 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003908 else if (xmlStrEqual(val, BAD_CAST "1"))
3909 def = 1;
3910 else if (xmlStrEqual(val, BAD_CAST "0"))
3911 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003912 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003913 xmlSchemaPSimpleTypeErr(ctxt,
3914 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003915 ownerDes, ownerItem, node,
3916 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3917 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003918 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003919 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003920}
3921
3922/************************************************************************
3923 * *
3924 * Shema extraction from an Infoset *
3925 * *
3926 ************************************************************************/
3927static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3928 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003929 xmlNodePtr node,
3930 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003931static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3932 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003933 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003934 xmlNodePtr node,
3935 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003936static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3937 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003938 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003939 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003940static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3941 xmlSchemaPtr schema,
3942 xmlNodePtr node);
3943static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3944 xmlSchemaPtr schema,
3945 xmlNodePtr node);
3946static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3947 ctxt,
3948 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003949 xmlNodePtr node,
3950 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003951static xmlSchemaAttributeGroupPtr
3952xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003953 xmlSchemaPtr schema, xmlNodePtr node,
3954 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003955static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3956 xmlSchemaPtr schema,
3957 xmlNodePtr node);
3958static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3959 xmlSchemaPtr schema,
3960 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003961static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003962xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3963 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003964
3965/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003966 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003967 *
3968 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003969 * @ownerDes: the designation of the parent element
3970 * @ownerItem: the schema object owner if existent
3971 * @attr: the schema attribute node being validated
3972 * @value: the value
3973 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003974 *
3975 * Validates a value against the given built-in type.
3976 * This one is intended to be used internally for validation
3977 * of schema attribute values during parsing of the schema.
3978 *
3979 * Returns 0 if the value is valid, a positive error code
3980 * number otherwise and -1 in case of an internal or API error.
3981 */
3982static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003983xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3984 xmlChar **ownerDes,
3985 xmlSchemaTypePtr ownerItem,
3986 xmlAttrPtr attr,
3987 const xmlChar *value,
3988 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003989{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003990
Daniel Veillardc0826a72004-08-10 14:17:33 +00003991 int ret = 0;
3992
3993 /*
3994 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3995 * one is really meant to be used internally, so better not.
3996 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003997 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003998 return (-1);
3999 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4000 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004001 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004002 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004003 "type '%s' is not a built-in type.\n",
4004 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004005 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004006 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004007 switch (type->builtInType) {
4008 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004009 case XML_SCHEMAS_QNAME:
4010 case XML_SCHEMAS_ANYURI:
4011 case XML_SCHEMAS_TOKEN:
4012 case XML_SCHEMAS_LANGUAGE:
4013 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4014 break;
4015
4016 /*
4017 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004018 ret = xmlValidateNCName(value, 1);
4019 break;
4020 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004021 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004022 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004023 "Internal error: xmlSchemaPvalueAttrNode, use "
4024 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4025 "for extracting QName valueues instead.\n",
4026 NULL, NULL);
4027 return (-1);
4028 case XML_SCHEMAS_ANYURI:
4029 if (value != NULL) {
4030 xmlURIPtr uri = xmlParseURI((const char *) value);
4031 if (uri == NULL)
4032 ret = 1;
4033 else
4034 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004035 }
4036 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004037 case XML_SCHEMAS_TOKEN: {
4038 const xmlChar *cur = value;
4039
4040 if (IS_BLANK_CH(*cur)) {
4041 ret = 1;
4042 } else while (*cur != 0) {
4043 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4044 ret = 1;
4045 break;
4046 } else if (*cur == ' ') {
4047 cur++;
4048 if ((*cur == 0) || (*cur == ' ')) {
4049 ret = 1;
4050 break;
4051 }
4052 } else {
4053 cur++;
4054 }
4055 }
4056 }
4057 break;
4058 case XML_SCHEMAS_LANGUAGE:
4059 if (xmlCheckLanguageID(value) != 1)
4060 ret = 1;
4061 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004062 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004063 default: {
4064 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004065 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004066 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004067 "valueidation using the type '%s' is not implemented "
4068 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004069 type->name, NULL);
4070 return (-1);
4071 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004072 }
4073 /*
4074 * TODO: Should we use the S4S error codes instead?
4075 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004076 if (ret < 0) {
4077 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4078 XML_SCHEMAP_INTERNAL,
4079 "Internal error: xmlSchemaPValAttrNodeValue, "
4080 "failed to validate a schema attribute value.\n",
4081 NULL, NULL);
4082 return (-1);
4083 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004084 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4085 xmlSchemaPSimpleTypeErr(ctxt,
4086 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4087 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004088 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004089 NULL, NULL, NULL);
4090 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4091 } else {
4092 xmlSchemaPSimpleTypeErr(ctxt,
4093 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4094 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004095 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004096 NULL, NULL, NULL);
4097 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4098 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004099 }
4100 return (ret);
4101}
4102
4103/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004104 * xmlSchemaPValAttrNode:
4105 *
4106 * @ctxt: a schema parser context
4107 * @ownerDes: the designation of the parent element
4108 * @ownerItem: the schema object owner if existent
4109 * @attr: the schema attribute node being validated
4110 * @type: the built-in type to be validated against
4111 * @value: the resulting value if any
4112 *
4113 * Extracts and validates a value against the given built-in type.
4114 * This one is intended to be used internally for validation
4115 * of schema attribute values during parsing of the schema.
4116 *
4117 * Returns 0 if the value is valid, a positive error code
4118 * number otherwise and -1 in case of an internal or API error.
4119 */
4120static int
4121xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4122 xmlChar **ownerDes,
4123 xmlSchemaTypePtr ownerItem,
4124 xmlAttrPtr attr,
4125 xmlSchemaTypePtr type,
4126 const xmlChar **value)
4127{
4128 const xmlChar *val;
4129
4130 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4131 return (-1);
4132
4133 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4134 if (value != NULL)
4135 *value = val;
4136
4137 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4138 val, type));
4139}
4140
4141/**
4142 * xmlSchemaPValAttr:
4143 *
4144 * @ctxt: a schema parser context
4145 * @node: the element node of the attribute
4146 * @ownerDes: the designation of the parent element
4147 * @ownerItem: the schema object owner if existent
4148 * @ownerElem: the owner element node
4149 * @name: the name of the schema attribute node
4150 * @type: the built-in type to be validated against
4151 * @value: the resulting value if any
4152 *
4153 * Extracts and validates a value against the given built-in type.
4154 * This one is intended to be used internally for validation
4155 * of schema attribute values during parsing of the schema.
4156 *
4157 * Returns 0 if the value is valid, a positive error code
4158 * number otherwise and -1 in case of an internal or API error.
4159 */
4160static int
4161xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4162 xmlChar **ownerDes,
4163 xmlSchemaTypePtr ownerItem,
4164 xmlNodePtr ownerElem,
4165 const char *name,
4166 xmlSchemaTypePtr type,
4167 const xmlChar **value)
4168{
4169 xmlAttrPtr attr;
4170
4171 if ((ctxt == NULL) || (type == NULL)) {
4172 if (value != NULL)
4173 *value = NULL;
4174 return (-1);
4175 }
4176 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4177 if (value != NULL)
4178 *value = NULL;
4179 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004180 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004181 "Internal error: xmlSchemaPValAttr, the given "
4182 "type '%s' is not a built-in type.\n",
4183 type->name, NULL);
4184 return (-1);
4185 }
4186 attr = xmlSchemaGetPropNode(ownerElem, name);
4187 if (attr == NULL) {
4188 if (value != NULL)
4189 *value = NULL;
4190 return (0);
4191 }
4192 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4193 type, value));
4194}
4195/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004196 * xmlSchemaParseAttrDecls:
4197 * @ctxt: a schema validation context
4198 * @schema: the schema being built
4199 * @node: a subtree containing XML Schema informations
4200 * @type: the hosting type
4201 *
4202 * parse a XML schema attrDecls declaration corresponding to
4203 * <!ENTITY % attrDecls
4204 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4205 */
4206static xmlNodePtr
4207xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4208 xmlNodePtr child, xmlSchemaTypePtr type)
4209{
4210 xmlSchemaAttributePtr lastattr, attr;
4211
4212 lastattr = NULL;
4213 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004214 (IS_SCHEMA(child, "attributeGroup"))) {
4215 attr = NULL;
4216 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004217 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004218 } else if (IS_SCHEMA(child, "attributeGroup")) {
4219 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004220 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004221 }
4222 if (attr != NULL) {
4223 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004224 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4225 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4226 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004227 type->attributes = attr;
4228 lastattr = attr;
4229 } else {
4230 lastattr->next = attr;
4231 lastattr = attr;
4232 }
4233 }
4234 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004235 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004236 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004237}
4238
4239/**
4240 * xmlSchemaParseAnnotation:
4241 * @ctxt: a schema validation context
4242 * @schema: the schema being built
4243 * @node: a subtree containing XML Schema informations
4244 *
4245 * parse a XML schema Attrribute declaration
4246 * *WARNING* this interface is highly subject to change
4247 *
William M. Bracke7091952004-05-11 15:09:58 +00004248 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004249 * 1 in case of success.
4250 */
4251static xmlSchemaAnnotPtr
4252xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4253 xmlNodePtr node)
4254{
4255 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004256 xmlNodePtr child = NULL;
4257 xmlAttrPtr attr;
4258 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004259
Daniel Veillardc0826a72004-08-10 14:17:33 +00004260 /*
4261 * INFO: S4S completed.
4262 */
4263 /*
4264 * id = ID
4265 * {any attributes with non-schema namespace . . .}>
4266 * Content: (appinfo | documentation)*
4267 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004268 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4269 return (NULL);
4270 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004271 attr = node->properties;
4272 while (attr != NULL) {
4273 if (((attr->ns == NULL) &&
4274 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4275 ((attr->ns != NULL) &&
4276 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4277
4278 xmlSchemaPIllegalAttrErr(ctxt,
4279 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4280 NULL, NULL, attr);
4281 }
4282 attr = attr->next;
4283 }
4284 /* TODO: Check id. */
4285
4286 /*
4287 * And now for the children...
4288 */
4289 child = node->children;
4290 while (child != NULL) {
4291 if (IS_SCHEMA(child, "appinfo")) {
4292 /* TODO: make available the content of "appinfo". */
4293 /*
4294 * source = anyURI
4295 * {any attributes with non-schema namespace . . .}>
4296 * Content: ({any})*
4297 */
4298 attr = child->properties;
4299 while (attr != NULL) {
4300 if (((attr->ns == NULL) &&
4301 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4302 ((attr->ns != NULL) &&
4303 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004304
Daniel Veillardc0826a72004-08-10 14:17:33 +00004305 xmlSchemaPIllegalAttrErr(ctxt,
4306 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4307 NULL, NULL, attr);
4308 }
4309 attr = attr->next;
4310 }
4311 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4312 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4313 child = child->next;
4314 } else if (IS_SCHEMA(child, "documentation")) {
4315 /* TODO: make available the content of "documentation". */
4316 /*
4317 * source = anyURI
4318 * {any attributes with non-schema namespace . . .}>
4319 * Content: ({any})*
4320 */
4321 attr = child->properties;
4322 while (attr != NULL) {
4323 if (attr->ns == NULL) {
4324 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4325 xmlSchemaPIllegalAttrErr(ctxt,
4326 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4327 NULL, NULL, attr);
4328 }
4329 } else {
4330 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4331 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4332 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4333
4334 xmlSchemaPIllegalAttrErr(ctxt,
4335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4336 NULL, NULL, attr);
4337 }
4338 }
4339 attr = attr->next;
4340 }
4341 /*
4342 * Attribute "xml:lang".
4343 */
4344 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4345 if (attr != NULL)
4346 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4347 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4348 child = child->next;
4349 } else {
4350 if (!barked)
4351 xmlSchemaPContentErr(ctxt,
4352 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4353 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4354 barked = 1;
4355 child = child->next;
4356 }
4357 }
4358
Daniel Veillard4255d502002-04-16 15:50:10 +00004359 return (ret);
4360}
4361
4362/**
4363 * xmlSchemaParseFacet:
4364 * @ctxt: a schema validation context
4365 * @schema: the schema being built
4366 * @node: a subtree containing XML Schema informations
4367 *
4368 * parse a XML schema Facet declaration
4369 * *WARNING* this interface is highly subject to change
4370 *
4371 * Returns the new type structure or NULL in case of error
4372 */
4373static xmlSchemaFacetPtr
4374xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004375 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004376{
4377 xmlSchemaFacetPtr facet;
4378 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004379 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004380
4381 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4382 return (NULL);
4383
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004384 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004385 if (facet == NULL) {
4386 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4387 return (NULL);
4388 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004389 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004390 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004391 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004392 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4393 "Facet %s has no value\n", node->name, NULL);
4394 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004395 return (NULL);
4396 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004397 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004398 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004399 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004400 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004401 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004402 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004403 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004404 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004405 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004407 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004409 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004410 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004412 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004413 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004414 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004415 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004416 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4419 } else if (IS_SCHEMA(node, "minLength")) {
4420 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4421 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4423 "Unknown facet type %s\n", node->name, NULL);
4424 xmlSchemaFreeFacet(facet);
4425 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004427 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004428 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004429 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4430 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4431 const xmlChar *fixed;
4432
4433 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4434 if (fixed != NULL) {
4435 if (xmlStrEqual(fixed, BAD_CAST "true"))
4436 facet->fixed = 1;
4437 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004438 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004439 child = node->children;
4440
4441 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004442 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4443 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004444 }
4445 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4447 "Facet %s has unexpected child content\n",
4448 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 }
4450 return (facet);
4451}
4452
4453/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004454 * xmlSchemaParseWildcardNs:
4455 * @ctxt: a schema parser context
4456 * @wildc: the wildcard, already created
4457 * @node: a subtree containing XML Schema informations
4458 *
4459 * Parses the attribute "processContents" and "namespace"
4460 * of a xsd:anyAttribute and xsd:any.
4461 * *WARNING* this interface is highly subject to change
4462 *
4463 * Returns 0 if everything goes fine, a positive error code
4464 * if something is not valid and -1 if an internal error occurs.
4465 */
4466static int
4467xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4468 xmlSchemaPtr schema,
4469 xmlSchemaWildcardPtr wildc,
4470 xmlNodePtr node)
4471{
4472 const xmlChar *pc, *ns, *dictnsItem;
4473 int ret = 0;
4474 xmlChar *nsItem;
4475 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4476 xmlAttrPtr attr;
4477
4478 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4479 if ((pc == NULL)
4480 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4481 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4482 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4483 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4484 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4485 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4486 } else {
4487 xmlSchemaPSimpleTypeErr(ctxt,
4488 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4489 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004490 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004491 NULL, NULL, NULL);
4492 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4493 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4494 }
4495 /*
4496 * Build the namespace constraints.
4497 */
4498 attr = xmlSchemaGetPropNode(node, "namespace");
4499 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4500 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4501 wildc->any = 1;
4502 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4503 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4504 if (wildc->negNsSet == NULL) {
4505 return (-1);
4506 }
4507 wildc->negNsSet->value = schema->targetNamespace;
4508 } else {
4509 const xmlChar *end, *cur;
4510
4511 cur = ns;
4512 do {
4513 while (IS_BLANK_CH(*cur))
4514 cur++;
4515 end = cur;
4516 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4517 end++;
4518 if (end == cur)
4519 break;
4520 nsItem = xmlStrndup(cur, end - cur);
4521 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4522 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4523 xmlSchemaPSimpleTypeErr(ctxt,
4524 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4525 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004526 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004527 "((##any | ##other) | List of (anyURI | "
4528 "(##targetNamespace | ##local)))",
4529 nsItem, NULL, NULL, NULL);
4530 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4531 } else {
4532 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4533 dictnsItem = schema->targetNamespace;
4534 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4535 dictnsItem = NULL;
4536 } else {
4537 /*
4538 * Validate the item (anyURI).
4539 */
4540 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4541 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4542 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4543 }
4544 /*
4545 * Avoid dublicate namespaces.
4546 */
4547 tmp = wildc->nsSet;
4548 while (tmp != NULL) {
4549 if (dictnsItem == tmp->value)
4550 break;
4551 tmp = tmp->next;
4552 }
4553 if (tmp == NULL) {
4554 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4555 if (tmp == NULL) {
4556 xmlFree(nsItem);
4557 return (-1);
4558 }
4559 tmp->value = dictnsItem;
4560 tmp->next = NULL;
4561 if (wildc->nsSet == NULL)
4562 wildc->nsSet = tmp;
4563 else
4564 lastNs->next = tmp;
4565 lastNs = tmp;
4566 }
4567
4568 }
4569 xmlFree(nsItem);
4570 cur = end;
4571 } while (*cur != 0);
4572 }
4573 return (ret);
4574}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004575
4576static int
4577xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4578 xmlSchemaTypePtr item,
4579 xmlNodePtr node,
4580 int minOccurs,
4581 int maxOccurs) {
4582
4583 if (maxOccurs != UNBOUNDED) {
4584 /*
4585 * TODO: Maby we should better not create the particle,
4586 * if min/max is invalid, since it could confuse the build of the
4587 * content model.
4588 */
4589 /*
4590 * 3.9.6 Schema Component Constraint: Particle Correct
4591 *
4592 */
4593 if (maxOccurs < 1) {
4594 /*
4595 * 2.2 {max occurs} must be greater than or equal to 1.
4596 */
4597 xmlSchemaPCustomAttrErr(ctxt,
4598 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4599 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4600 "The value must be greater than or equal to 1");
4601 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4602 } else if (minOccurs > maxOccurs) {
4603 /*
4604 * 2.1 {min occurs} must not be greater than {max occurs}.
4605 */
4606 xmlSchemaPCustomAttrErr(ctxt,
4607 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4608 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4609 "The value must not be greater than the value of 'maxOccurs'");
4610 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4611 }
4612 }
4613 return (0);
4614}
4615
Daniel Veillardc0826a72004-08-10 14:17:33 +00004616/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004617 * xmlSchemaParseAny:
4618 * @ctxt: a schema validation context
4619 * @schema: the schema being built
4620 * @node: a subtree containing XML Schema informations
4621 *
4622 * parse a XML schema Any declaration
4623 * *WARNING* this interface is highly subject to change
4624 *
4625 * Returns the new type structure or NULL in case of error
4626 */
4627static xmlSchemaTypePtr
4628xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4629 xmlNodePtr node)
4630{
4631 xmlSchemaTypePtr type;
4632 xmlNodePtr child = NULL;
4633 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004634 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004635 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004636
4637 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4638 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004639 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4640 "(nonNegativeInteger | unbounded)");
4641 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4642 "nonNegativeInteger");
4643 if ((minOccurs == 0) && (maxOccurs == 0))
4644 return (NULL);
4645
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004646 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004647 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004648 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004649 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004650 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004651 type->type = XML_SCHEMA_TYPE_ANY;
4652
Daniel Veillardc0826a72004-08-10 14:17:33 +00004653 wildc = xmlSchemaAddWildcard(ctxt);
4654 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004655 * Check min/max sanity.
4656 */
4657 type->maxOccurs = maxOccurs;
4658 type->minOccurs = minOccurs;
4659 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4660 node, type->minOccurs, type->maxOccurs);
4661 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004662 * This is not nice, since it is won't be used as a attribute wildcard,
4663 * but better than adding a field to the structure.
4664 */
4665 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004666 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004667 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004668 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004669 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4670 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004671 }
4672 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004673 xmlSchemaPErr2(ctxt, node, child,
4674 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4675 "Sequence %s has unexpected content\n", type->name,
4676 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004677 }
4678
4679 return (type);
4680}
4681
4682/**
4683 * xmlSchemaParseNotation:
4684 * @ctxt: a schema validation context
4685 * @schema: the schema being built
4686 * @node: a subtree containing XML Schema informations
4687 *
4688 * parse a XML schema Notation declaration
4689 *
4690 * Returns the new structure or NULL in case of error
4691 */
4692static xmlSchemaNotationPtr
4693xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004694 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004695{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004696 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004697 xmlSchemaNotationPtr ret;
4698 xmlNodePtr child = NULL;
4699
4700 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4701 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004702 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004703 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004704 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4705 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004706 return (NULL);
4707 }
4708 ret = xmlSchemaAddNotation(ctxt, schema, name);
4709 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004710 return (NULL);
4711 }
4712 child = node->children;
4713 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004714 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4715 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004716 }
4717 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004718 xmlSchemaPErr2(ctxt, node, child,
4719 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4720 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004721 }
4722
4723 return (ret);
4724}
4725
4726/**
4727 * xmlSchemaParseAnyAttribute:
4728 * @ctxt: a schema validation context
4729 * @schema: the schema being built
4730 * @node: a subtree containing XML Schema informations
4731 *
4732 * parse a XML schema AnyAttrribute declaration
4733 * *WARNING* this interface is highly subject to change
4734 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004735 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004736 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004737static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004738xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4739 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004740{
Daniel Veillard3646d642004-06-02 19:19:14 +00004741 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004742 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004743 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004744
4745 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4746 return (NULL);
4747
Daniel Veillard3646d642004-06-02 19:19:14 +00004748 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004749 if (ret == NULL) {
4750 return (NULL);
4751 }
William M. Bracke7091952004-05-11 15:09:58 +00004752 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004753 /*
4754 * Check for illegal attributes.
4755 */
4756 attr = node->properties;
4757 while (attr != NULL) {
4758 if (attr->ns == NULL) {
4759 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4760 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4761 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4762 xmlSchemaPIllegalAttrErr(ctxt,
4763 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4764 NULL, NULL, attr);
4765 }
4766 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4767 xmlSchemaPIllegalAttrErr(ctxt,
4768 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4769 NULL, NULL, attr);
4770 }
4771 attr = attr->next;
4772 }
4773 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4774 /*
4775 * Parse the namespace list.
4776 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004777 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4778 xmlSchemaFreeWildcard(ret);
4779 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004780 }
4781 /*
4782 * And now for the children...
4783 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004784 child = node->children;
4785 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004786 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4787 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004788 }
4789 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004790 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004791 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4792 NULL, NULL, node, child,
4793 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 }
4795
4796 return (ret);
4797}
4798
4799
4800/**
4801 * xmlSchemaParseAttribute:
4802 * @ctxt: a schema validation context
4803 * @schema: the schema being built
4804 * @node: a subtree containing XML Schema informations
4805 *
4806 * parse a XML schema Attrribute declaration
4807 * *WARNING* this interface is highly subject to change
4808 *
William M. Bracke7091952004-05-11 15:09:58 +00004809 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 */
4811static xmlSchemaAttributePtr
4812xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004813 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004814{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004815 const xmlChar *name, *attrValue;
4816 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004817 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004818 xmlNodePtr child = NULL;
4819 xmlAttrPtr attr, nameAttr;
4820 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004821
4822 /*
4823 * Note that the w3c spec assumes the schema to be validated with schema
4824 * for schemas beforehand.
4825 *
4826 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004827 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004828
4829 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4830 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004831 attr = xmlSchemaGetPropNode(node, "ref");
4832 nameAttr = xmlSchemaGetPropNode(node, "name");
4833
4834 if ((attr == NULL) && (nameAttr == NULL)) {
4835 /*
4836 * 3.2.3 : 3.1
4837 * One of ref or name must be present, but not both
4838 */
4839 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4840 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4841 "One of the attributes 'ref' or 'name' must be present");
4842 return (NULL);
4843 }
4844 if ((topLevel) || (attr == NULL)) {
4845 if (nameAttr == NULL) {
4846 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4847 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4848 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004849 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004850 }
4851 } else
4852 isRef = 1;
4853
4854 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004855 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004856 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4857
4858 /*
4859 * Parse as attribute reference.
4860 */
4861 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4862 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4863 &refPrefix, &ref) != 0) {
4864 return (NULL);
4865 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004866 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004867 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004868 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004869 if (ret == NULL) {
4870 if (repName != NULL)
4871 xmlFree(repName);
4872 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004873 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004874 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4875 ret->node = node;
4876 ret->refNs = refNs;
4877 ret->refPrefix = refPrefix;
4878 ret->ref = ref;
4879 /*
4880 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4881 */
4882 if (nameAttr != NULL)
4883 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4884 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4885 "ref", "name");
4886 /*
4887 * Check for illegal attributes.
4888 */
4889 attr = node->properties;
4890 while (attr != NULL) {
4891 if (attr->ns == NULL) {
4892 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4893 xmlStrEqual(attr->name, BAD_CAST "form")) {
4894 /*
4895 * 3.2.3 : 3.2
4896 * If ref is present, then all of <simpleType>,
4897 * form and type must be absent.
4898 */
4899 xmlSchemaPIllegalAttrErr(ctxt,
4900 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4901 (xmlSchemaTypePtr) ret, attr);
4902 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4903 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4904 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4905 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4906 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4907 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4908 xmlSchemaPIllegalAttrErr(ctxt,
4909 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4910 &repName, (xmlSchemaTypePtr) ret, attr);
4911 }
4912 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4913 xmlSchemaPIllegalAttrErr(ctxt,
4914 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4915 &repName, (xmlSchemaTypePtr) ret, attr);
4916 }
4917 attr = attr->next;
4918 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004919 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004920 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004921
4922 /*
4923 * Parse as attribute declaration.
4924 */
4925 if (xmlSchemaPValAttrNode(ctxt,
4926 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4927 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4928 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004929 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004930 /*
4931 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4932 */
4933 /*
4934 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4935 */
4936 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4937 xmlSchemaPSimpleTypeErr(ctxt,
4938 XML_SCHEMAP_NO_XMLNS,
4939 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004940 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004941 "The value must not match 'xmlns'",
4942 NULL, NULL);
4943 if (repName != NULL)
4944 xmlFree(repName);
4945 return (NULL);
4946 }
4947 /*
4948 * Evaluate the target namespace
4949 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004950 if (topLevel) {
4951 ns = schema->targetNamespace;
4952 } else {
4953 attr = xmlSchemaGetPropNode(node, "form");
4954 if (attr != NULL) {
4955 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4956 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4957 ns = schema->targetNamespace;
4958 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4959 xmlSchemaPSimpleTypeErr(ctxt,
4960 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4961 &repName, NULL, (xmlNodePtr) attr,
4962 NULL, "(qualified | unqualified)",
4963 attrValue, NULL, NULL, NULL);
4964 }
4965 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4966 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004967 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004968 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004969 if (ret == NULL) {
4970 if (repName != NULL)
4971 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004972 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004973 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004974 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4975 ret->node = node;
4976 if (topLevel)
4977 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4978 /*
4979 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4980 */
4981 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4982 xmlSchemaPCustomErr(ctxt,
4983 XML_SCHEMAP_NO_XSI,
4984 &repName, (xmlSchemaTypePtr) ret, node,
4985 "The target namespace must not match '%s'",
4986 xmlSchemaInstanceNs);
4987 }
4988 /*
4989 * Check for illegal attributes.
4990 */
4991 attr = node->properties;
4992 while (attr != NULL) {
4993 if (attr->ns == NULL) {
4994 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4995 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4996 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4997 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4998 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4999 if ((topLevel) ||
5000 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5001 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5002 xmlSchemaPIllegalAttrErr(ctxt,
5003 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5004 &repName, (xmlSchemaTypePtr) ret, attr);
5005 }
5006 }
5007 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5008 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5009 &repName, (xmlSchemaTypePtr) ret, attr);
5010 }
5011 attr = attr->next;
5012 }
5013 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5014 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005015 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005016 /* TODO: Check ID. */
5017 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005018 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005019 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005020 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005021 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5022 if (ret->defValue != NULL)
5023 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5024 /*
5025 * Attribute "default".
5026 */
5027 attr = xmlSchemaGetPropNode(node, "default");
5028 if (attr != NULL) {
5029 /*
5030 * 3.2.3 : 1
5031 * default and fixed must not both be present.
5032 */
5033 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5034 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5035 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5036 } else
5037 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5038 }
5039 if (topLevel == 0) {
5040 /*
5041 * Attribute "use".
5042 */
5043 attr = xmlSchemaGetPropNode(node, "use");
5044 if (attr != NULL) {
5045 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5046 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5047 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5048 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5049 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5050 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5051 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5052 else
5053 xmlSchemaPSimpleTypeErr(ctxt,
5054 XML_SCHEMAP_INVALID_ATTR_USE,
5055 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005056 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005057 attrValue, NULL, NULL, NULL);
5058 } else
5059 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5060 /*
5061 * 3.2.3 : 2
5062 * If default and use are both present, use must have
5063 * the actual value optional.
5064 */
5065 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5066 (ret->defValue != NULL) &&
5067 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5068 xmlSchemaPSimpleTypeErr(ctxt,
5069 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5070 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005071 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005072 "The value must be 'optional' if the attribute "
5073 "'default' is present as well", NULL, NULL);
5074 }
5075 }
5076 /*
5077 * And now for the children...
5078 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005079 child = node->children;
5080 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005081 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5082 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005083 }
5084 if (isRef) {
5085 if (child != NULL) {
5086 if (IS_SCHEMA(child, "simpleType"))
5087 /*
5088 * 3.2.3 : 3.2
5089 * If ref is present, then all of <simpleType>,
5090 * form and type must be absent.
5091 */
5092 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5093 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5094 "(annotation?)");
5095 else
5096 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5097 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5098 "(annotation?)");
5099 }
5100 } else {
5101 if (IS_SCHEMA(child, "simpleType")) {
5102 if (ret->typeName != NULL) {
5103 /*
5104 * 3.2.3 : 4
5105 * type and <simpleType> must not both be present.
5106 */
5107 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5108 &repName, (xmlSchemaTypePtr) ret, node, child,
5109 "The attribute 'type' and the <simpleType> child "
5110 "are mutually exclusive", NULL);
5111 } else
5112 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5113 child = child->next;
5114 }
5115 if (child != NULL)
5116 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5117 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5118 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005119 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005120 /*
5121 * Cleanup.
5122 */
5123 if (repName != NULL)
5124 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005125 return (ret);
5126}
5127
5128/**
5129 * xmlSchemaParseAttributeGroup:
5130 * @ctxt: a schema validation context
5131 * @schema: the schema being built
5132 * @node: a subtree containing XML Schema informations
5133 *
5134 * parse a XML schema Attribute Group declaration
5135 * *WARNING* this interface is highly subject to change
5136 *
5137 * Returns the attribute group or NULL in case of error.
5138 */
5139static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005140xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005141 xmlSchemaPtr schema, xmlNodePtr node,
5142 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005143{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005144 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005145 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005146 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005147 const xmlChar *oldcontainer;
5148 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005149
5150 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5151 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005152
5153 nameAttr = xmlSchemaGetPropNode(node, "name");
5154 attr = xmlSchemaGetPropNode(node, "ref");
5155 if ((topLevel) || (attr == NULL)) {
5156 /*
5157 * Parse as an attribute group definition.
5158 * Note that those are allowed at top level only.
5159 */
5160 if (nameAttr == NULL) {
5161 xmlSchemaPMissingAttrErr(ctxt,
5162 XML_SCHEMAP_S4S_ATTR_MISSING,
5163 NULL, NULL, node, "name", NULL);
5164 return (NULL);
5165 }
5166 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5167 /*
5168 * The name is crucial, exit if invalid.
5169 */
5170 if (xmlSchemaPValAttrNode(ctxt,
5171 NULL, NULL, nameAttr,
5172 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5173 return (NULL);
5174 }
5175 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5176 if (ret == NULL)
5177 return (NULL);
5178 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5179 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5180 ret->node = node;
5181 } else {
5182 char buf[50];
5183 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5184
5185 /*
5186 * Parse as an attribute group definition reference.
5187 */
5188 if (attr == NULL) {
5189 xmlSchemaPMissingAttrErr(ctxt,
5190 XML_SCHEMAP_S4S_ATTR_MISSING,
5191 NULL, NULL, node, "ref", NULL);
5192 }
5193 xmlSchemaPValAttrNodeQName(ctxt, schema,
5194 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5195
5196 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5197 name = (const xmlChar *) buf;
5198 if (name == NULL) {
5199 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5200 "attribute group definition reference", node);
5201 return (NULL);
5202 }
5203 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5204 if (ret == NULL)
5205 return (NULL);
5206 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5207 ret->ref = ref;
5208 ret->refNs = refNs;
5209 /* TODO: Is @refPrefix currently used? */
5210 ret->refPrefix = refPrefix;
5211 ret->node = node;
5212 }
5213 /*
5214 * Check for illegal attributes.
5215 */
5216 attr = node->properties;
5217 while (attr != NULL) {
5218 if (attr->ns == NULL) {
5219 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5220 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5221 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5222 {
5223 xmlSchemaPIllegalAttrErr(ctxt,
5224 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5225 NULL, NULL, attr);
5226 }
5227 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5228 xmlSchemaPIllegalAttrErr(ctxt,
5229 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5230 NULL, NULL, attr);
5231 }
5232 attr = attr->next;
5233 }
5234 /* TODO: Validate "id" ? */
5235 /*
5236 * And now for the children...
5237 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005238 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005239 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005240 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005242 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5243 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005245 if (topLevel) {
5246 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5247 if (IS_SCHEMA(child, "anyAttribute")) {
5248 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5249 child = child->next;
5250 }
5251 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005253 xmlSchemaPContentErr(ctxt,
5254 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5255 NULL, NULL, node, child, NULL,
5256 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005257 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005258 ctxt->container = oldcontainer;
5259 return (ret);
5260}
5261
5262/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005263 * xmlSchemaPValAttrFormDefault:
5264 * @value: the value
5265 * @flags: the flags to be modified
5266 * @flagQualified: the specific flag for "qualified"
5267 *
5268 * Returns 0 if the value is valid, 1 otherwise.
5269 */
5270static int
5271xmlSchemaPValAttrFormDefault(const xmlChar *value,
5272 int *flags,
5273 int flagQualified)
5274{
5275 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5276 if ((*flags & flagQualified) == 0)
5277 *flags |= flagQualified;
5278 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5279 return (1);
5280
5281 return (0);
5282}
5283
5284/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005285 * xmlSchemaPValAttrBlockFinal:
5286 * @value: the value
5287 * @flags: the flags to be modified
5288 * @flagAll: the specific flag for "#all"
5289 * @flagExtension: the specific flag for "extension"
5290 * @flagRestriction: the specific flag for "restriction"
5291 * @flagSubstitution: the specific flag for "substitution"
5292 * @flagList: the specific flag for "list"
5293 * @flagUnion: the specific flag for "union"
5294 *
5295 * Validates the value of the attribute "final" and "block". The value
5296 * is converted into the specified flag values and returned in @flags.
5297 *
5298 * Returns 0 if the value is valid, 1 otherwise.
5299 */
5300
5301static int
5302xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5303 int *flags,
5304 int flagAll,
5305 int flagExtension,
5306 int flagRestriction,
5307 int flagSubstitution,
5308 int flagList,
5309 int flagUnion)
5310{
5311 int ret = 0;
5312
5313 /*
5314 * TODO: This does not check for dublicate entries.
5315 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005316 if (value == NULL)
5317 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005318 if (xmlStrEqual(value, BAD_CAST "#all")) {
5319 if (flagAll != -1)
5320 *flags |= flagAll;
5321 else {
5322 if (flagExtension != -1)
5323 *flags |= flagExtension;
5324 if (flagRestriction != -1)
5325 *flags |= flagRestriction;
5326 if (flagSubstitution != -1)
5327 *flags |= flagSubstitution;
5328 if (flagList != -1)
5329 *flags |= flagList;
5330 if (flagUnion != -1)
5331 *flags |= flagUnion;
5332 }
5333 } else {
5334 const xmlChar *end, *cur = value;
5335 xmlChar *item;
5336
5337 do {
5338 while (IS_BLANK_CH(*cur))
5339 cur++;
5340 end = cur;
5341 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5342 end++;
5343 if (end == cur)
5344 break;
5345 item = xmlStrndup(cur, end - cur);
5346 if (xmlStrEqual(item, BAD_CAST "extension")) {
5347 if (flagExtension != -1) {
5348 if ((*flags & flagExtension) == 0)
5349 *flags |= flagExtension;
5350 } else
5351 ret = 1;
5352 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5353 if (flagRestriction != -1) {
5354 if ((*flags & flagRestriction) == 0)
5355 *flags |= flagRestriction;
5356 } else
5357 ret = 1;
5358 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5359 if (flagSubstitution != -1) {
5360 if ((*flags & flagSubstitution) == 0)
5361 *flags |= flagSubstitution;
5362 } else
5363 ret = 1;
5364 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5365 if (flagList != -1) {
5366 if ((*flags & flagList) == 0)
5367 *flags |= flagList;
5368 } else
5369 ret = 1;
5370 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5371 if (flagUnion != -1) {
5372 if ((*flags & flagUnion) == 0)
5373 *flags |= flagUnion;
5374 } else
5375 ret = 1;
5376 } else
5377 ret = 1;
5378 if (item != NULL)
5379 xmlFree(item);
5380 cur = end;
5381 } while ((ret == 0) && (*cur != 0));
5382 }
5383
5384 return (ret);
5385}
5386
5387/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005388 * xmlSchemaParseElement:
5389 * @ctxt: a schema validation context
5390 * @schema: the schema being built
5391 * @node: a subtree containing XML Schema informations
5392 *
5393 * parse a XML schema Element declaration
5394 * *WARNING* this interface is highly subject to change
5395 *
William M. Bracke7091952004-05-11 15:09:58 +00005396 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005397 */
5398static xmlSchemaElementPtr
5399xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005400 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005401{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005402 const xmlChar *name = NULL;
5403 const xmlChar *attrValue;
5404 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005405 xmlSchemaElementPtr ret;
5406 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005407 const xmlChar *oldcontainer;
5408 xmlAttrPtr attr, nameAttr;
5409 int minOccurs, maxOccurs;
5410 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005411
5412 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5413 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005414
Daniel Veillard4255d502002-04-16 15:50:10 +00005415 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5416 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005417
Daniel Veillardc0826a72004-08-10 14:17:33 +00005418 oldcontainer = ctxt->container;
5419
5420 nameAttr = xmlSchemaGetPropNode(node, "name");
5421 attr = xmlSchemaGetPropNode(node, "ref");
5422 if ((topLevel) || (attr == NULL)) {
5423 if (nameAttr == NULL) {
5424 xmlSchemaPMissingAttrErr(ctxt,
5425 XML_SCHEMAP_S4S_ATTR_MISSING,
5426 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5427 "name", NULL);
5428 return (NULL);
5429 }
5430 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5431 } else {
5432 isRef = 1;
5433
5434 }
5435 /*
5436 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5437 * to no component at all
5438 * TODO: It might be better to validate the element, even if it won't be
5439 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005440 */
5441 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5442 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005443 if ((minOccurs == 0) && (maxOccurs == 0))
5444 return (NULL);
5445 /*
5446 * If we get a "ref" attribute on a local <element> we will assume it's
5447 * a reference - even if there's a "name" attribute; this seems to be more
5448 * robust.
5449 */
5450 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005451 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005452 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5453
5454 /*
5455 * Parse as a particle.
5456 */
5457 xmlSchemaPValAttrNodeQName(ctxt, schema,
5458 (xmlChar **) &xmlSchemaElemDesAttrRef,
5459 NULL, attr, &refNs, &refPrefix, &ref);
5460
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005461 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005462 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005463 if (ret == NULL) {
5464 if (repName != NULL)
5465 xmlFree(repName);
5466 return (NULL);
5467 }
5468 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5469 ret->node = node;
5470 ret->ref = ref;
5471 ret->refNs = refNs;
5472 ret->refPrefix = refPrefix;
5473 ret->flags |= XML_SCHEMAS_ELEM_REF;
5474 /*
5475 * Check for illegal attributes.
5476 */
5477 /*
5478 * 3.3.3 : 2.1
5479 * One of ref or name must be present, but not both
5480 */
5481 if (nameAttr != NULL) {
5482 xmlSchemaPMutualExclAttrErr(ctxt,
5483 XML_SCHEMAP_SRC_ELEMENT_2_1,
5484 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5485 "ref", "name");
5486 }
5487 /* 3.3.3 : 2.2 */
5488 attr = node->properties;
5489 while (attr != NULL) {
5490 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005491 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5492 xmlStrEqual(attr->name, BAD_CAST "name") ||
5493 xmlStrEqual(attr->name, BAD_CAST "id") ||
5494 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5495 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5496 {
5497 attr = attr->next;
5498 continue;
5499 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005500 xmlSchemaPCustomAttrErr(ctxt,
5501 XML_SCHEMAP_SRC_ELEMENT_2_2,
5502 &repName, (xmlSchemaTypePtr) ret, attr,
5503 "Only the attributes 'minOccurs', 'maxOccurs' and "
5504 "'id' are allowed in addition to 'ref'");
5505 break;
5506 }
5507 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5508 xmlSchemaPIllegalAttrErr(ctxt,
5509 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5510 &repName, (xmlSchemaTypePtr) ret, attr);
5511 }
5512 attr = attr->next;
5513 }
5514 } else {
5515 const xmlChar *ns = NULL, *fixed;
5516
5517 /*
5518 * Parse as an element declaration.
5519 */
5520 if (xmlSchemaPValAttrNode(ctxt,
5521 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5522 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5523 return (NULL);
5524 /*
5525 * Evaluate the target namespace.
5526 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005527 if (topLevel) {
5528 ns = schema->targetNamespace;
5529 } else {
5530 attr = xmlSchemaGetPropNode(node, "form");
5531 if (attr != NULL) {
5532 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5533 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005534 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005535 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5536 xmlSchemaPSimpleTypeErr(ctxt,
5537 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5538 &repName, NULL, (xmlNodePtr) attr,
5539 NULL, "(qualified | unqualified)",
5540 attrValue, NULL, NULL, NULL);
5541 }
5542 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5543 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005544 }
5545 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005546 if (ret == NULL) {
5547 if (repName != NULL)
5548 xmlFree(repName);
5549 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005550 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005551 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5552 ret->node = node;
5553 /*
5554 * Check for illegal attributes.
5555 */
William M. Bracke7091952004-05-11 15:09:58 +00005556 attr = node->properties;
5557 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005558 if (attr->ns == NULL) {
5559 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5560 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5561 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5562 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5563 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5564 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005565 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5566 {
5567 if (topLevel == 0) {
5568 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005569 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005570 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5571 {
5572 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5573 /*
5574 * 3.3.6 : 3 If there is a non-·absent· {substitution
5575 * group affiliation}, then {scope} must be global.
5576 * TODO: This one is redundant, since the S4S does
5577 * prohibit this attribute on local declarations already;
5578 * so why an explicit error code? Weird spec.
5579 * TODO: Move this to the proper constraint layer.
5580 * TODO: Or better wait for spec 1.1 to come.
5581 */
5582 xmlSchemaPIllegalAttrErr(ctxt,
5583 XML_SCHEMAP_E_PROPS_CORRECT_3,
5584 &repName, (xmlSchemaTypePtr) ret, attr);
5585 } else {
5586 xmlSchemaPIllegalAttrErr(ctxt,
5587 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5588 &repName, (xmlSchemaTypePtr) ret, attr);
5589 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 }
5591 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5592 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5593 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5594
5595 xmlSchemaPIllegalAttrErr(ctxt,
5596 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5597 &repName, (xmlSchemaTypePtr) ret, attr);
5598 }
5599 }
5600 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5601
5602 xmlSchemaPIllegalAttrErr(ctxt,
5603 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5604 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005605 }
5606 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005607 }
William M. Bracke7091952004-05-11 15:09:58 +00005608 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005609 * Extract/validate attributes.
5610 */
5611 if (topLevel) {
5612 /*
5613 * Process top attributes of global element declarations here.
5614 */
5615 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5616 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5617 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5618 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5619 &(ret->substGroupNs), NULL, &(ret->substGroup));
5620 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5621 node, "abstract", 0))
5622 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5623 /*
5624 * Attribute "final".
5625 */
5626 attr = xmlSchemaGetPropNode(node, "final");
5627 if (attr == NULL) {
5628 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5629 } else {
5630 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5631 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5632 -1,
5633 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5634 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5635 xmlSchemaPSimpleTypeErr(ctxt,
5636 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5637 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005638 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005639 attrValue, NULL, NULL, NULL);
5640 }
5641 }
5642 }
5643 /*
5644 * Attribute "block".
5645 */
5646 attr = xmlSchemaGetPropNode(node, "block");
5647 if (attr == NULL) {
5648 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5649 } else {
5650 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5651 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5652 -1,
5653 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5654 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5655 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5656 xmlSchemaPSimpleTypeErr(ctxt,
5657 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5658 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005659 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005660 "restriction | substitution))", attrValue,
5661 NULL, NULL, NULL);
5662 }
5663 }
5664 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5665 node, "nillable", 0))
5666 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005667
Daniel Veillardc0826a72004-08-10 14:17:33 +00005668 xmlSchemaPValAttrQName(ctxt, schema,
5669 &repName, (xmlSchemaTypePtr) ret, node,
5670 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005671
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5673 attr = xmlSchemaGetPropNode(node, "fixed");
5674 if (attr != NULL) {
5675 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5676 if (ret->value != NULL) {
5677 /*
5678 * 3.3.3 : 1
5679 * default and fixed must not both be present.
5680 */
5681 xmlSchemaPMutualExclAttrErr(ctxt,
5682 XML_SCHEMAP_SRC_ELEMENT_1,
5683 &repName, (xmlSchemaTypePtr) ret, attr,
5684 "default", "fixed");
5685 } else {
5686 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5687 ret->value = fixed;
5688 }
5689 }
5690 }
5691 /*
5692 * Extract/validate common attributes.
5693 */
5694 /* TODO: Check ID: */
5695 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5696 ret->minOccurs = minOccurs;
5697 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005698 if (topLevel != 1)
5699 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5700 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005701 /*
5702 * And now for the children...
5703 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005704 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005705 child = node->children;
5706 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005707 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5708 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005709 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005710 if (isRef) {
5711 if (child != NULL) {
5712 xmlSchemaPContentErr(ctxt,
5713 XML_SCHEMAP_SRC_ELEMENT_2_2,
5714 &repName, (xmlSchemaTypePtr) ret, node, child,
5715 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005716 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005717 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005718 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005719 /*
5720 * 3.3.3 : 3
5721 * "type" and either <simpleType> or <complexType> are mutually
5722 * exclusive
5723 */
William M. Bracke7091952004-05-11 15:09:58 +00005724 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005725 xmlSchemaPContentErr(ctxt,
5726 XML_SCHEMAP_SRC_ELEMENT_3,
5727 &repName, (xmlSchemaTypePtr) ret, node, child,
5728 "The attribute 'type' and the <complexType> child are "
5729 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005730 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005731 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005732 child = child->next;
5733 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 /*
5735 * 3.3.3 : 3
5736 * "type" and either <simpleType> or <complexType> are
5737 * mutually exclusive
5738 */
William M. Bracke7091952004-05-11 15:09:58 +00005739 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005740 xmlSchemaPContentErr(ctxt,
5741 XML_SCHEMAP_SRC_ELEMENT_3,
5742 &repName, (xmlSchemaTypePtr) ret, node, child,
5743 "The attribute 'type' and the <simpleType> child are "
5744 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005745 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005746 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005747 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005748 }
William M. Bracke7091952004-05-11 15:09:58 +00005749 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005750 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcik48307f42004-11-12 15:16:25 +00005751 TODO child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00005752 }
5753 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005754 xmlSchemaPContentErr(ctxt,
5755 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5756 &repName, (xmlSchemaTypePtr) ret, node, child,
5757 NULL, "(annotation?, ((simpleType | complexType)?, "
5758 "(unique | key | keyref)*))");
5759 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005760
Daniel Veillardc0826a72004-08-10 14:17:33 +00005761 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005762 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005763 /*
5764 * Cleanup.
5765 */
5766 if (repName != NULL)
5767 xmlFree(repName);
5768 /*
5769 * NOTE: Element Declaration Representation OK 4. will be checked at a
5770 * different layer.
5771 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005772 return (ret);
5773}
5774
5775/**
5776 * xmlSchemaParseUnion:
5777 * @ctxt: a schema validation context
5778 * @schema: the schema being built
5779 * @node: a subtree containing XML Schema informations
5780 *
5781 * parse a XML schema Union definition
5782 * *WARNING* this interface is highly subject to change
5783 *
William M. Bracke7091952004-05-11 15:09:58 +00005784 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005785 * 1 in case of success.
5786 */
5787static xmlSchemaTypePtr
5788xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005789 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005790{
5791 xmlSchemaTypePtr type, subtype, last = NULL;
5792 xmlNodePtr child = NULL;
5793 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005794 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005795
5796 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5797 return (NULL);
5798
William M. Brack2f2a6632004-08-20 23:09:47 +00005799 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5800 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005801 if (type == NULL)
5802 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005803 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005804 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005805 /*
5806 * Check for illegal attributes.
5807 */
5808 attr = node->properties;
5809 while (attr != NULL) {
5810 if (attr->ns == NULL) {
5811 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5812 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5813 xmlSchemaPIllegalAttrErr(ctxt,
5814 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5815 NULL, type, attr);
5816 }
5817 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5818 xmlSchemaPIllegalAttrErr(ctxt,
5819 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5820 NULL, type, attr);
5821 }
5822 attr = attr->next;
5823 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005824 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005825 /*
5826 * Attribute "memberTypes". This is a list of QNames.
5827 * TODO: Validate the QNames.
5828 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005829 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005830 /*
5831 * And now for the children...
5832 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005833 child = node->children;
5834 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005835 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5836 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005838 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005839 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005840 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005841 if (subtype != NULL) {
5842 if (last == NULL) {
5843 type->subtypes = subtype;
5844 last = subtype;
5845 } else {
5846 last->next = subtype;
5847 last = subtype;
5848 }
5849 last->next = NULL;
5850 }
5851 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005852 }
5853 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005854 /* TODO: Think about the error code. */
5855 xmlSchemaPContentErr(ctxt,
5856 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5857 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005858 }
5859 return (type);
5860}
5861
5862/**
5863 * xmlSchemaParseList:
5864 * @ctxt: a schema validation context
5865 * @schema: the schema being built
5866 * @node: a subtree containing XML Schema informations
5867 *
5868 * parse a XML schema List definition
5869 * *WARNING* this interface is highly subject to change
5870 *
William M. Bracke7091952004-05-11 15:09:58 +00005871 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005872 * 1 in case of success.
5873 */
5874static xmlSchemaTypePtr
5875xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005876 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005877{
5878 xmlSchemaTypePtr type, subtype;
5879 xmlNodePtr child = NULL;
5880 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005881 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005882
5883 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5884 return (NULL);
5885
William M. Brack2f2a6632004-08-20 23:09:47 +00005886 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5887 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005888 if (type == NULL)
5889 return (NULL);
5890 type->node = node;
5891 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005892 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005893 /*
5894 * Check for illegal attributes.
5895 */
5896 attr = node->properties;
5897 while (attr != NULL) {
5898 if (attr->ns == NULL) {
5899 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5900 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5901 xmlSchemaPIllegalAttrErr(ctxt,
5902 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5903 NULL, type, attr);
5904 }
5905 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5906 xmlSchemaPIllegalAttrErr(ctxt,
5907 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5908 NULL, type, attr);
5909 }
5910 attr = attr->next;
5911 }
5912 /*
5913 * Attribute "itemType".
5914 */
5915 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5916 node, "itemType", &(type->baseNs), NULL, &(type->base));
5917 /*
5918 * And now for the children...
5919 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005920 child = node->children;
5921 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005922 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5923 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005924 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005925 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005926 if (IS_SCHEMA(child, "simpleType")) {
5927 if (type->base != NULL) {
5928 xmlSchemaPCustomErr(ctxt,
5929 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5930 NULL, type, node,
5931 "The attribute 'itemType' and the <simpleType> child "
5932 "are mutually exclusive", NULL);
5933 } else {
5934 subtype = (xmlSchemaTypePtr)
5935 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5936 type->subtypes = subtype;
5937 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005938 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005939 }
5940 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005941 /* TODO: Think about the error code. */
5942 xmlSchemaPContentErr(ctxt,
5943 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5944 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005945 }
5946 return (type);
5947}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005948
Daniel Veillard4255d502002-04-16 15:50:10 +00005949/**
5950 * xmlSchemaParseSimpleType:
5951 * @ctxt: a schema validation context
5952 * @schema: the schema being built
5953 * @node: a subtree containing XML Schema informations
5954 *
5955 * parse a XML schema Simple Type definition
5956 * *WARNING* this interface is highly subject to change
5957 *
William M. Bracke7091952004-05-11 15:09:58 +00005958 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005959 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005960 */
5961static xmlSchemaTypePtr
5962xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005963 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005964{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005965 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005966 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005967 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005968 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005970
5971 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5972 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005973
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005975 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005976 if (attr == NULL) {
5977 xmlSchemaPMissingAttrErr(ctxt,
5978 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005979 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005980 "name", NULL);
5981 return (NULL);
5982 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005983 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005985 return (NULL);
5986 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005987 }
5988
5989 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005990 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005991
Daniel Veillard01fa6152004-06-29 17:04:39 +00005992 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005993 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005994 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005995 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005996 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005997 if (type == NULL)
5998 return (NULL);
5999 type->node = node;
6000 type->type = XML_SCHEMA_TYPE_SIMPLE;
6001 /*
6002 * Check for illegal attributes.
6003 */
6004 attr = node->properties;
6005 while (attr != NULL) {
6006 if (attr->ns == NULL) {
6007 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6008 xmlSchemaPIllegalAttrErr(ctxt,
6009 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006010 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006011 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006012 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6013 xmlSchemaPIllegalAttrErr(ctxt,
6014 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006015 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006016 }
6017 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006018 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006019 } else {
6020 /*
6021 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006022 *
6023 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006024 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006025 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006026 if (type == NULL)
6027 return (NULL);
6028 type->node = node;
6029 type->type = XML_SCHEMA_TYPE_SIMPLE;
6030 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6031 /*
6032 * Check for illegal attributes.
6033 */
6034 attr = node->properties;
6035 while (attr != NULL) {
6036 if (attr->ns == NULL) {
6037 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6038 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006039 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006040 xmlSchemaPIllegalAttrErr(ctxt,
6041 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006042 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006043 }
6044 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6045 xmlSchemaPIllegalAttrErr(ctxt,
6046 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006047 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006048 }
6049 attr = attr->next;
6050 }
6051 /*
6052 * Attribute "final".
6053 */
6054 attr = xmlSchemaGetPropNode(node, "final");
6055 if (attr == NULL) {
6056 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6057 } else {
6058 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6059 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6060 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6061 XML_SCHEMAS_TYPE_FINAL_LIST,
6062 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6063
6064 xmlSchemaPSimpleTypeErr(ctxt,
6065 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006066 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006067 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006068 attrValue, NULL, NULL, NULL);
6069 }
6070 }
6071 }
6072 /* TODO: Check id. */
6073 type->id = xmlSchemaGetProp(ctxt, node, "id");
6074 /*
6075 * And now for the children...
6076 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006077 oldCtxtType = ctxt->ctxtType;
6078 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006079 ctxt->ctxtType = type;
6080 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006081 child = node->children;
6082 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006083 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6084 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006085 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006086 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006089 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006090 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006092 subtype = (xmlSchemaTypePtr)
6093 xmlSchemaParseList(ctxt, schema, child);
6094 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006095 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006096 subtype = (xmlSchemaTypePtr)
6097 xmlSchemaParseUnion(ctxt, schema, child);
6098 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006099 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006100 type->subtypes = subtype;
6101 if ((child != NULL) || (subtype == NULL)) {
6102 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006103 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006104 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006105 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006106 ctxt->parentItem = oldParentItem;
6107 ctxt->ctxtType = oldCtxtType;
6108 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006109
Daniel Veillard4255d502002-04-16 15:50:10 +00006110 return (type);
6111}
6112
6113
6114/**
6115 * xmlSchemaParseGroup:
6116 * @ctxt: a schema validation context
6117 * @schema: the schema being built
6118 * @node: a subtree containing XML Schema informations
6119 *
6120 * parse a XML schema Group definition
6121 * *WARNING* this interface is highly subject to change
6122 *
William M. Bracke7091952004-05-11 15:09:58 +00006123 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006124 * 1 in case of success.
6125 */
6126static xmlSchemaTypePtr
6127xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006128 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006129{
6130 xmlSchemaTypePtr type, subtype;
6131 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006132 const xmlChar *name;
6133 const xmlChar *ref = NULL, *refNs = NULL;
6134 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006135 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006136
6137 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6138 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006139 /*
6140 * TODO: Validate the element even if no item is created
6141 * (i.e. min/maxOccurs == 0).
6142 */
6143 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6144 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6145 if ((minOccurs == 0) && (maxOccurs == 0)) {
6146 return (NULL);
6147 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006148 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006149 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006150 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6151 if (ref == NULL) {
6152 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006153 XML_SCHEMAP_GROUP_NONAME_NOREF,
6154 "Group definition or particle: One of the attributes \"name\" "
6155 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006156 return (NULL);
6157 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006158 if (refNs == NULL)
6159 refNs = schema->targetNamespace;
6160 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
6161 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006162 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006163 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006164 if (type == NULL)
6165 return (NULL);
6166 type->node = node;
6167 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00006168 if (topLevel)
6169 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006170 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 type->ref = ref;
6172 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006173 type->minOccurs = minOccurs;
6174 type->maxOccurs = maxOccurs;
6175 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006176 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006177
6178 child = node->children;
6179 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006180 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6181 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006182 }
6183 subtype = NULL;
6184 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006185 subtype = (xmlSchemaTypePtr)
6186 xmlSchemaParseAll(ctxt, schema, child);
6187 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006188 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6190 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006192 subtype = (xmlSchemaTypePtr)
6193 xmlSchemaParseSequence(ctxt, schema, child);
6194 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006195 }
6196 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006197 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006198 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006199 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006200 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006201 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 }
6203
6204 return (type);
6205}
6206
6207/**
6208 * xmlSchemaParseAll:
6209 * @ctxt: a schema validation context
6210 * @schema: the schema being built
6211 * @node: a subtree containing XML Schema informations
6212 *
6213 * parse a XML schema All definition
6214 * *WARNING* this interface is highly subject to change
6215 *
William M. Bracke7091952004-05-11 15:09:58 +00006216 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006217 * 1 in case of success.
6218 */
6219static xmlSchemaTypePtr
6220xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006221 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006222{
6223 xmlSchemaTypePtr type, subtype, last = NULL;
6224 xmlNodePtr child = NULL;
6225 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006226 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006227
6228 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6229 return (NULL);
6230
6231
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006232 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006233 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006234 if (type == NULL)
6235 return (NULL);
6236 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006237 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006238 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006239
6240 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6241 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006242
6243 oldcontainer = ctxt->container;
6244 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006245 child = node->children;
6246 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006247 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6248 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006249 }
6250 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006251 subtype = (xmlSchemaTypePtr)
6252 xmlSchemaParseElement(ctxt, schema, child, 0);
6253 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006254 if (subtype->minOccurs > 1)
6255 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006256 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006257 NULL, NULL);
6258 if (subtype->maxOccurs > 1)
6259 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006260 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006261 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006262 if (last == NULL) {
6263 type->subtypes = subtype;
6264 last = subtype;
6265 } else {
6266 last->next = subtype;
6267 last = subtype;
6268 }
6269 last->next = NULL;
6270 }
6271 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006272 }
6273 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006274 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006275 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006276 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006277 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006278 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006279 return (type);
6280}
6281
6282/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006283 * xmlSchemaCleanupDoc:
6284 * @ctxt: a schema validation context
6285 * @node: the root of the document.
6286 *
6287 * removes unwanted nodes in a schemas document tree
6288 */
6289static void
6290xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6291{
6292 xmlNodePtr delete, cur;
6293
6294 if ((ctxt == NULL) || (root == NULL)) return;
6295
6296 /*
6297 * Remove all the blank text nodes
6298 */
6299 delete = NULL;
6300 cur = root;
6301 while (cur != NULL) {
6302 if (delete != NULL) {
6303 xmlUnlinkNode(delete);
6304 xmlFreeNode(delete);
6305 delete = NULL;
6306 }
6307 if (cur->type == XML_TEXT_NODE) {
6308 if (IS_BLANK_NODE(cur)) {
6309 if (xmlNodeGetSpacePreserve(cur) != 1) {
6310 delete = cur;
6311 }
6312 }
6313 } else if ((cur->type != XML_ELEMENT_NODE) &&
6314 (cur->type != XML_CDATA_SECTION_NODE)) {
6315 delete = cur;
6316 goto skip_children;
6317 }
6318
6319 /*
6320 * Skip to next node
6321 */
6322 if (cur->children != NULL) {
6323 if ((cur->children->type != XML_ENTITY_DECL) &&
6324 (cur->children->type != XML_ENTITY_REF_NODE) &&
6325 (cur->children->type != XML_ENTITY_NODE)) {
6326 cur = cur->children;
6327 continue;
6328 }
6329 }
6330 skip_children:
6331 if (cur->next != NULL) {
6332 cur = cur->next;
6333 continue;
6334 }
6335
6336 do {
6337 cur = cur->parent;
6338 if (cur == NULL)
6339 break;
6340 if (cur == root) {
6341 cur = NULL;
6342 break;
6343 }
6344 if (cur->next != NULL) {
6345 cur = cur->next;
6346 break;
6347 }
6348 } while (cur != NULL);
6349 }
6350 if (delete != NULL) {
6351 xmlUnlinkNode(delete);
6352 xmlFreeNode(delete);
6353 delete = NULL;
6354 }
6355}
6356
William M. Brack2f2a6632004-08-20 23:09:47 +00006357
6358/**
6359 * xmlSchemaImportSchema
6360 *
6361 * @ctxt: a schema validation context
6362 * @schemaLocation: an URI defining where to find the imported schema
6363 *
6364 * import a XML schema
6365 * *WARNING* this interface is highly subject to change
6366 *
6367 * Returns -1 in case of error and 1 in case of success.
6368 */
6369#if 0
6370static xmlSchemaImportPtr
6371xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6372 const xmlChar *schemaLocation)
6373{
6374 xmlSchemaImportPtr import;
6375 xmlSchemaParserCtxtPtr newctxt;
6376
6377 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6378 if (newctxt == NULL) {
6379 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6380 NULL);
6381 return (NULL);
6382 }
6383 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6384 /* Keep the same dictionnary for parsing, really */
6385 xmlDictReference(ctxt->dict);
6386 newctxt->dict = ctxt->dict;
6387 newctxt->includes = 0;
6388 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6389
6390 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6391 ctxt->userData);
6392
6393 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6394 if (import == NULL) {
6395 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6396 NULL);
6397 xmlSchemaFreeParserCtxt(newctxt);
6398 return (NULL);
6399 }
6400
6401 memset(import, 0, sizeof(xmlSchemaImport));
6402 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6403 import->schema = xmlSchemaParse(newctxt);
6404
6405 if (import->schema == NULL) {
6406 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006407 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006408 "Failed to import schema from location \"%s\".\n",
6409 schemaLocation, NULL);
6410
6411 xmlSchemaFreeParserCtxt(newctxt);
6412 /* The schemaLocation is held by the dictionary.
6413 if (import->schemaLocation != NULL)
6414 xmlFree((xmlChar *)import->schemaLocation);
6415 */
6416 xmlFree(import);
6417 return NULL;
6418 }
6419
6420 xmlSchemaFreeParserCtxt(newctxt);
6421 return import;
6422}
6423#endif
6424
6425static void
6426xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6427{
6428 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6429 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6430
6431 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6432 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6433
6434 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6435 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6436 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6437 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6438 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6439 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6440 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6441 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6442
6443 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6444 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6445 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6446 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6447 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6448 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6449}
6450
6451static void
6452xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6453 xmlSchemaPtr schema,
6454 xmlNodePtr node)
6455{
6456 xmlAttrPtr attr;
6457 const xmlChar *val;
6458
6459 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6460 if (attr != NULL) {
6461 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6462 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6463 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6464 xmlSchemaPSimpleTypeErr(ctxt,
6465 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6466 NULL, NULL, (xmlNodePtr) attr, NULL,
6467 "(qualified | unqualified)", val, NULL, NULL, NULL);
6468 }
6469 }
6470
6471 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6472 if (attr != NULL) {
6473 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6474 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6475 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6476 xmlSchemaPSimpleTypeErr(ctxt,
6477 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6478 NULL, NULL, (xmlNodePtr) attr, NULL,
6479 "(qualified | unqualified)", val, NULL, NULL, NULL);
6480 }
6481 }
6482
6483 attr = xmlSchemaGetPropNode(node, "finalDefault");
6484 if (attr != NULL) {
6485 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6486 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6487 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6488 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6489 -1,
6490 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6491 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6492 xmlSchemaPSimpleTypeErr(ctxt,
6493 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6494 NULL, NULL, (xmlNodePtr) attr, NULL,
6495 "(#all | List of (extension | restriction | list | union))",
6496 val, NULL, NULL, NULL);
6497 }
6498 }
6499
6500 attr = xmlSchemaGetPropNode(node, "blockDefault");
6501 if (attr != NULL) {
6502 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6503 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6504 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6505 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6506 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6507 xmlSchemaPSimpleTypeErr(ctxt,
6508 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6509 NULL, NULL, (xmlNodePtr) attr, NULL,
6510 "(#all | List of (extension | restriction | substitution))",
6511 val, NULL, NULL, NULL);
6512 }
6513 }
6514}
6515
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006516/**
6517 * xmlSchemaParseSchemaTopLevel:
6518 * @ctxt: a schema validation context
6519 * @schema: the schemas
6520 * @nodes: the list of top level nodes
6521 *
6522 * Returns the internal XML Schema structure built from the resource or
6523 * NULL in case of error
6524 */
6525static void
6526xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6527 xmlSchemaPtr schema, xmlNodePtr nodes)
6528{
6529 xmlNodePtr child;
6530 xmlSchemaAnnotPtr annot;
6531
6532 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6533 return;
6534
6535 child = nodes;
6536 while ((IS_SCHEMA(child, "include")) ||
6537 (IS_SCHEMA(child, "import")) ||
6538 (IS_SCHEMA(child, "redefine")) ||
6539 (IS_SCHEMA(child, "annotation"))) {
6540 if (IS_SCHEMA(child, "annotation")) {
6541 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6542 if (schema->annot == NULL)
6543 schema->annot = annot;
6544 else
6545 xmlSchemaFreeAnnot(annot);
6546 } else if (IS_SCHEMA(child, "import")) {
6547 xmlSchemaParseImport(ctxt, schema, child);
6548 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006549 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006550 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006551 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006552 } else if (IS_SCHEMA(child, "redefine")) {
6553 TODO
6554 }
6555 child = child->next;
6556 }
6557 while (child != NULL) {
6558 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006559 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006560 child = child->next;
6561 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006562 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006563 child = child->next;
6564 } else if (IS_SCHEMA(child, "element")) {
6565 xmlSchemaParseElement(ctxt, schema, child, 1);
6566 child = child->next;
6567 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006568 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006569 child = child->next;
6570 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006571 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006572 child = child->next;
6573 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006574 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006575 child = child->next;
6576 } else if (IS_SCHEMA(child, "notation")) {
6577 xmlSchemaParseNotation(ctxt, schema, child);
6578 child = child->next;
6579 } else {
6580 xmlSchemaPErr2(ctxt, NULL, child,
6581 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006582 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006583 child->name, NULL);
6584 child = child->next;
6585 }
6586 while (IS_SCHEMA(child, "annotation")) {
6587 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6588 if (schema->annot == NULL)
6589 schema->annot = annot;
6590 else
6591 xmlSchemaFreeAnnot(annot);
6592 child = child->next;
6593 }
6594 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006595 ctxt->parentItem = NULL;
6596 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006597}
6598
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006599static xmlSchemaImportPtr
6600xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6601 xmlHashTablePtr *imports,
6602 const xmlChar *nsName)
6603{
6604 xmlSchemaImportPtr ret;
6605
6606 if (*imports == NULL) {
6607 *imports = xmlHashCreate(10);
6608 if (*imports == NULL) {
6609 xmlSchemaPCustomErr(ctxt,
6610 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6611 NULL, NULL, (xmlNodePtr) ctxt->doc,
6612 "Internal error: failed to build the import table",
6613 NULL);
6614 return (NULL);
6615 }
6616 }
6617 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6618 if (ret == NULL) {
6619 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6620 return (NULL);
6621 }
6622 memset(ret, 0, sizeof(xmlSchemaImport));
6623 if (nsName == NULL)
6624 nsName = XML_SCHEMAS_NO_NAMESPACE;
6625 xmlHashAddEntry(*imports, nsName, ret);
6626
6627 return (ret);
6628}
6629
6630static int
6631xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006632 xmlSchemaPtr schema,
6633 xmlNodePtr node,
6634 const xmlChar *nsName,
6635 const xmlChar *location,
6636 xmlDocPtr *doc,
6637 const xmlChar **targetNamespace,
6638 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006639{
6640 xmlParserCtxtPtr parserCtxt;
6641 xmlSchemaImportPtr import;
6642 const xmlChar *ns;
6643 xmlNodePtr root;
6644
6645 /*
6646 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6647 * <xsi:noNamespaceSchemaLocation>.
6648 */
6649 *doc = NULL;
6650 /*
6651 * Given that the schemaLocation [attribute] is only a hint, it is open
6652 * to applications to ignore all but the first <import> for a given
6653 * namespace, regardless of the ·actual value· of schemaLocation, but
6654 * such a strategy risks missing useful information when new
6655 * schemaLocations are offered.
6656 *
6657 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6658 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6659 * valid or not.
6660 * We will follow XSV here.
6661 */
6662 if (location == NULL) {
6663 /*
6664 * Schema Document Location Strategy:
6665 *
6666 * 3 Based on the namespace name, identify an existing schema document,
6667 * either as a resource which is an XML document or a <schema> element
6668 * information item, in some local schema repository;
6669 *
6670 * 5 Attempt to resolve the namespace name to locate such a resource.
6671 *
6672 * NOTE: Those stategies are not supported, so we will skip.
6673 */
6674 return (0);
6675 }
6676 if (nsName == NULL)
6677 ns = XML_SCHEMAS_NO_NAMESPACE;
6678 else
6679 ns = nsName;
6680
6681 import = xmlHashLookup(schema->schemasImports, ns);
6682 if (import != NULL) {
6683 /*
6684 * There was a valid resource for the specified namespace already
6685 * defined, so skip.
6686 * TODO: This might be changed someday to allow import of
6687 * components from multiple documents for a single target namespace.
6688 */
6689 return (0);
6690 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006691
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006692 /*
6693 * Schema Document Location Strategy:
6694 *
6695 * 2 Based on the location URI, identify an existing schema document,
6696 * either as a resource which is an XML document or a <schema> element
6697 * information item, in some local schema repository;
6698 *
6699 * 4 Attempt to resolve the location URI, to locate a resource on the
6700 * web which is or contains or references a <schema> element;
6701 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6702 *
6703 */
6704 if ((absolute == 0) && (node != NULL)) {
6705 xmlChar *base, *URI;
6706
6707 base = xmlNodeGetBase(node->doc, node);
6708 if (base == NULL) {
6709 URI = xmlBuildURI(location, node->doc->URL);
6710 } else {
6711 URI = xmlBuildURI(location, base);
6712 xmlFree(base);
6713 }
6714 if (URI != NULL) {
6715 location = xmlDictLookup(ctxt->dict, URI, -1);
6716 xmlFree(URI);
6717 }
6718 }
6719 parserCtxt = xmlNewParserCtxt();
6720 if (parserCtxt == NULL) {
6721 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6722 "allocating a parser context", NULL);
6723 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00006724 }
6725
6726 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
6727 xmlDictFree(parserCtxt->dict);
6728 parserCtxt->dict = ctxt->dict;
6729 xmlDictReference(parserCtxt->dict);
6730 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006731
6732 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6733 NULL, SCHEMAS_PARSE_OPTIONS);
6734
6735 /*
6736 * 2.1 The referent is (a fragment of) a resource which is an
6737 * XML document (see clause 1.1), which in turn corresponds to
6738 * a <schema> element information item in a well-formed information
6739 * set, which in turn corresponds to a valid schema.
6740 * TODO: What to do with the "fragment" stuff?
6741 *
6742 * 2.2 The referent is a <schema> element information item in
6743 * a well-formed information set, which in turn corresponds
6744 * to a valid schema.
6745 * NOTE: 2.2 won't apply, since only XML documents will be processed
6746 * here.
6747 */
6748 if (*doc == NULL) {
6749 xmlErrorPtr lerr;
6750 /*
6751 * It is *not* an error for the application schema reference
6752 * strategy to fail.
6753 *
6754 * If the doc is NULL and the parser error is an IO error we
6755 * will assume that the resource could not be located or accessed.
6756 *
6757 * TODO: Try to find specific error codes to react only on
6758 * localisation failures.
6759 *
6760 * TODO, FIXME: Check the spec: is a namespace added to the imported
6761 * namespaces, even if the schemaLocation did not provide
6762 * a resource? I guess so, since omitting the "schemaLocation"
6763 * attribute, imports a namespace as well.
6764 */
6765 lerr = xmlGetLastError();
6766 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6767 xmlFreeParserCtxt(parserCtxt);
6768 return(0);
6769 }
6770
6771 xmlSchemaPCustomErr(ctxt,
6772 XML_SCHEMAP_SRC_IMPORT_2_1,
6773 NULL, NULL, node,
6774 "Failed to parse the resource '%s' for import",
6775 location);
6776 xmlFreeParserCtxt(parserCtxt);
6777 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6778 }
6779 xmlFreeParserCtxt(parserCtxt);
6780
6781 root = xmlDocGetRootElement(*doc);
6782 if (root == NULL) {
6783 xmlSchemaPCustomErr(ctxt,
6784 XML_SCHEMAP_SRC_IMPORT_2_1,
6785 NULL, NULL, node,
6786 "The XML document '%s' to be imported has no document "
6787 "element", location);
6788 xmlFreeDoc(*doc);
6789 *doc = NULL;
6790 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6791 }
6792
6793 xmlSchemaCleanupDoc(ctxt, root);
6794
6795 if (!IS_SCHEMA(root, "schema")) {
6796 xmlSchemaPCustomErr(ctxt,
6797 XML_SCHEMAP_SRC_IMPORT_2_1,
6798 NULL, NULL, node,
6799 "The XML document '%s' to be imported is not a XML schema document",
6800 location);
6801 xmlFreeDoc(*doc);
6802 *doc = NULL;
6803 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6804 }
6805 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6806 /*
6807 * Schema Representation Constraint: Import Constraints and Semantics
6808 */
6809 if (nsName == NULL) {
6810 if (*targetNamespace != NULL) {
6811 xmlSchemaPCustomErr(ctxt,
6812 XML_SCHEMAP_SRC_IMPORT_3_2,
6813 NULL, NULL, node,
6814 "The XML schema to be imported is not expected "
6815 "to have a target namespace; this differs from "
6816 "its target namespace of '%s'", *targetNamespace);
6817 xmlFreeDoc(*doc);
6818 *doc = NULL;
6819 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6820 }
6821 } else {
6822 if (*targetNamespace == NULL) {
6823 xmlSchemaPCustomErr(ctxt,
6824 XML_SCHEMAP_SRC_IMPORT_3_1,
6825 NULL, NULL, node,
6826 "The XML schema to be imported is expected to have a target "
6827 "namespace of '%s'", nsName);
6828 xmlFreeDoc(*doc);
6829 *doc = NULL;
6830 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6831 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6832 xmlSchemaPCustomErrExt(ctxt,
6833 XML_SCHEMAP_SRC_IMPORT_3_1,
6834 NULL, NULL, node,
6835 "The XML schema to be imported is expected to have a "
6836 "target namespace of '%s'; this differs from "
6837 "its target namespace of '%s'",
6838 nsName, *targetNamespace, NULL);
6839 xmlFreeDoc(*doc);
6840 *doc = NULL;
6841 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6842 }
6843 }
6844
6845 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6846 if (import == NULL) {
6847 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6848 NULL, NULL, NULL,
6849 "Internal error: xmlSchemaAcquireSchemaDoc, "
6850 "failed to build import table", NULL);
6851 xmlFreeDoc(*doc);
6852 *doc = NULL;
6853 return (-1);
6854 }
6855 import->schemaLocation = location;
6856 import->doc = *doc;
6857 return (0);
6858}
William M. Brack2f2a6632004-08-20 23:09:47 +00006859
6860/**
6861 * xmlSchemaParseImport:
6862 * @ctxt: a schema validation context
6863 * @schema: the schema being built
6864 * @node: a subtree containing XML Schema informations
6865 *
6866 * parse a XML schema Import definition
6867 * *WARNING* this interface is highly subject to change
6868 *
6869 * Returns 0 in case of success, a positive error code if
6870 * not valid and -1 in case of an internal error.
6871 */
6872static int
6873xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6874 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006875{
6876 xmlNodePtr child;
6877 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006878 const xmlChar *schemaLocation = NULL;
6879 const xmlChar *targetNamespace, *oldTNS, *url;
6880 xmlAttrPtr attr;
6881 xmlDocPtr doc;
6882 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006883 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006884
6885
6886 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6887 return (-1);
6888
6889 /*
6890 * Check for illegal attributes.
6891 */
6892 attr = node->properties;
6893 while (attr != NULL) {
6894 if (attr->ns == NULL) {
6895 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6896 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6897 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6898 xmlSchemaPIllegalAttrErr(ctxt,
6899 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6900 NULL, NULL, attr);
6901 }
6902 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6903 xmlSchemaPIllegalAttrErr(ctxt,
6904 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6905 NULL, NULL, attr);
6906 }
6907 attr = attr->next;
6908 }
6909 /*
6910 * Extract and validate attributes.
6911 */
6912 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6913 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6914 &namespace) != 0) {
6915 xmlSchemaPSimpleTypeErr(ctxt,
6916 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6917 NULL, NULL, node,
6918 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6919 NULL, namespace, NULL, NULL, NULL);
6920 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6921 }
6922
6923 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6924 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6925 &schemaLocation) != 0) {
6926 xmlSchemaPSimpleTypeErr(ctxt,
6927 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6928 NULL, NULL, node,
6929 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6930 NULL, namespace, NULL, NULL, NULL);
6931 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6932 }
6933 /*
6934 * And now for the children...
6935 */
6936 child = node->children;
6937 if (IS_SCHEMA(child, "annotation")) {
6938 /*
6939 * the annotation here is simply discarded ...
6940 */
6941 child = child->next;
6942 }
6943 if (child != NULL) {
6944 xmlSchemaPContentErr(ctxt,
6945 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6946 NULL, NULL, node, child, NULL,
6947 "(annotation?)");
6948 }
6949 /*
6950 * Apply additional constraints.
6951 */
6952 if (namespace != NULL) {
6953 /*
6954 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6955 * must not match the ·actual value· of the enclosing <schema>'s
6956 * targetNamespace [attribute].
6957 */
6958 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6959 xmlSchemaPCustomErr(ctxt,
6960 XML_SCHEMAP_SRC_IMPORT_1_1,
6961 NULL, NULL, node,
6962 "The value of the attribute 'namespace' must not match "
6963 "the target namespace '%s' of the importing schema",
6964 schema->targetNamespace);
6965 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6966 }
6967 } else {
6968 /*
6969 * 1.2 If the namespace [attribute] is not present, then the enclosing
6970 * <schema> must have a targetNamespace [attribute].
6971 */
6972 if (schema->targetNamespace == NULL) {
6973 xmlSchemaPCustomErr(ctxt,
6974 XML_SCHEMAP_SRC_IMPORT_1_2,
6975 NULL, NULL, node,
6976 "The attribute 'namespace' must be existent if "
6977 "the importing schema has no target namespace",
6978 NULL);
6979 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6980 }
6981 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006982 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006983 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006984 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006985 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6986 schemaLocation, &doc, &targetNamespace, 0);
6987 if (ret != 0) {
6988 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006989 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006990 return (ret);
6991 } else if (doc != NULL) {
6992 /*
6993 * Save and reset the context & schema.
6994 */
6995 url = ctxt->URL;
6996 /* TODO: Is using the doc->URL here correct? */
6997 ctxt->URL = doc->URL;
6998 flags = schema->flags;
6999 oldTNS = schema->targetNamespace;
7000 /*
7001 * Parse the schema.
7002 */
7003 root = xmlDocGetRootElement(doc);
7004 xmlSchemaClearSchemaDefaults(schema);
7005 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7006 schema->targetNamespace = targetNamespace;
7007 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7008 /*
7009 * Restore the context & schema.
7010 */
7011 schema->flags = flags;
7012 schema->targetNamespace = oldTNS;
7013 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007014 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007015
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007016 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007017}
7018
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007019/**
7020 * xmlSchemaParseInclude:
7021 * @ctxt: a schema validation context
7022 * @schema: the schema being built
7023 * @node: a subtree containing XML Schema informations
7024 *
7025 * parse a XML schema Include definition
7026 *
William M. Bracke7091952004-05-11 15:09:58 +00007027 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007028 * 1 in case of success.
7029 */
7030static int
7031xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7032 xmlNodePtr node)
7033{
7034 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007035 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007036 xmlDocPtr doc;
7037 xmlNodePtr root;
7038 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007039 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007040 xmlAttrPtr attr;
7041 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007042 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007043
7044
7045 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7046 return (-1);
7047
7048 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007049 * Check for illegal attributes.
7050 */
7051 attr = node->properties;
7052 while (attr != NULL) {
7053 if (attr->ns == NULL) {
7054 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7055 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7056 xmlSchemaPIllegalAttrErr(ctxt,
7057 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7058 NULL, NULL, attr);
7059 }
7060 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7061 xmlSchemaPIllegalAttrErr(ctxt,
7062 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7063 NULL, NULL, attr);
7064 }
7065 attr = attr->next;
7066 }
7067 /*
7068 * Extract and validate attributes.
7069 */
7070 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007071 * Preliminary step, extract the URI-Reference for the include and
7072 * make an URI from the base.
7073 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007074 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7075 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007076 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007077 xmlChar *uri = NULL;
7078
7079 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7080 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7081 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007082 base = xmlNodeGetBase(node->doc, node);
7083 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007084 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007085 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007086 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007087 xmlFree(base);
7088 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007089 if (uri != NULL) {
7090 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7091 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007092 }
7093 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007094 xmlSchemaPMissingAttrErr(ctxt,
7095 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7096 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007097 return (-1);
7098 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007099 /*
7100 * And now for the children...
7101 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007102 child = node->children;
7103 while (IS_SCHEMA(child, "annotation")) {
7104 /*
7105 * the annotations here are simply discarded ...
7106 */
7107 child = child->next;
7108 }
7109 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007110 xmlSchemaPContentErr(ctxt,
7111 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7112 NULL, NULL, node, child, NULL,
7113 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007114 }
7115
7116 /*
7117 * First step is to parse the input document into an DOM/Infoset
7118 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007119 /*
7120 * TODO: Use xmlCtxtReadFile to share the dictionary.
7121 */
7122 parserCtxt = xmlNewParserCtxt();
7123 if (parserCtxt == NULL) {
7124 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7125 "allocating a parser context", NULL);
7126 return(-1);
7127 }
7128
7129 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7130 xmlDictFree(parserCtxt->dict);
7131 parserCtxt->dict = ctxt->dict;
7132 xmlDictReference(parserCtxt->dict);
7133 }
7134
7135 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7136 NULL, SCHEMAS_PARSE_OPTIONS);
7137 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007138 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007139 /*
7140 * TODO: It is not an error for the ·actual value· of the
7141 * schemaLocation [attribute] to fail to resolve it all, in which
7142 * case no corresponding inclusion is performed.
7143 * So do we need a warning report here?
7144 */
7145 xmlSchemaPCustomErr(ctxt,
7146 XML_SCHEMAP_FAILED_LOAD,
7147 NULL, NULL, node,
7148 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007149 return(-1);
7150 }
7151
7152 /*
7153 * Then extract the root of the schema
7154 */
7155 root = xmlDocGetRootElement(doc);
7156 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007157 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007158 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007159 NULL, NULL, node,
7160 "The included document '%s' has no document "
7161 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007162 xmlFreeDoc(doc);
7163 return (-1);
7164 }
7165
7166 /*
7167 * Remove all the blank text nodes
7168 */
7169 xmlSchemaCleanupDoc(ctxt, root);
7170
7171 /*
7172 * Check the schemas top level element
7173 */
7174 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007175 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007176 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007177 NULL, NULL, node,
7178 "The document '%s' to be included is not a schema document",
7179 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007180 xmlFreeDoc(doc);
7181 return (-1);
7182 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007183
William M. Brack2f2a6632004-08-20 23:09:47 +00007184 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007185 /*
7186 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7187 * value· is identical to the ·actual value· of the targetNamespace
7188 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7189 */
7190 if (targetNamespace != NULL) {
7191 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007192 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007193 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007194 NULL, NULL, node,
7195 "The target namespace of the included schema "
7196 "'%s' has to be absent, since the including schema "
7197 "has no target namespace",
7198 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007199 xmlFreeDoc(doc);
7200 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007201 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7202 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007203 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007204 NULL, NULL, node,
7205 "The target namespace '%s' of the included schema '%s' "
7206 "differs from '%s' of the including schema",
7207 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007208 xmlFreeDoc(doc);
7209 return (-1);
7210 }
7211 } else if (schema->targetNamespace != NULL) {
7212 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7213 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7214 } else
7215 wasConvertingNs = 1;
7216 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007217 /*
7218 * register the include
7219 */
7220 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7221 if (include == NULL) {
7222 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7223 xmlFreeDoc(doc);
7224 return (-1);
7225 }
7226
7227 memset(include, 0, sizeof(xmlSchemaInclude));
7228 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7229 include->doc = doc;
7230 include->next = schema->includes;
7231 schema->includes = include;
7232
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007233 /*
7234 * parse the declarations in the included file like if they
7235 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007236 */
7237 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007238 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007239 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007240 /*
7241 * The default values ("blockDefault", "elementFormDefault", etc.)
7242 * are set to the values of the included schema and restored afterwards.
7243 */
7244 saveFlags = schema->flags;
7245 xmlSchemaClearSchemaDefaults(schema);
7246 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007247 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007248 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007249 /*
7250 * Remove the converting flag.
7251 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007252 if ((wasConvertingNs == 0) &&
7253 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007254 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007255 return (1);
7256}
7257
7258/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007259 * xmlSchemaParseChoice:
7260 * @ctxt: a schema validation context
7261 * @schema: the schema being built
7262 * @node: a subtree containing XML Schema informations
7263 *
7264 * parse a XML schema Choice definition
7265 * *WARNING* this interface is highly subject to change
7266 *
William M. Bracke7091952004-05-11 15:09:58 +00007267 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007268 * 1 in case of success.
7269 */
7270static xmlSchemaTypePtr
7271xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007272 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007273{
7274 xmlSchemaTypePtr type, subtype, last = NULL;
7275 xmlNodePtr child = NULL;
7276 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007277 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007278 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007279
7280 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7281 return (NULL);
7282
7283
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007284 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007285 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007286 if (type == NULL)
7287 return (NULL);
7288 type->node = node;
7289 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007290 /*
7291 * Check for illegal attributes.
7292 */
7293 attr = node->properties;
7294 while (attr != NULL) {
7295 if (attr->ns == NULL) {
7296 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7297 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7298 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7299 xmlSchemaPIllegalAttrErr(ctxt,
7300 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7301 NULL, type, attr);
7302 }
7303 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7304 xmlSchemaPIllegalAttrErr(ctxt,
7305 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7306 NULL, type, attr);
7307 }
7308 attr = attr->next;
7309 }
7310 /*
7311 * Extract and validate attributes.
7312 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007313 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007314 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7315 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7316 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007317 /*
7318 * And now for the children...
7319 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007320 oldcontainer = ctxt->container;
7321 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007322 child = node->children;
7323 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007324 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7325 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007326 }
7327 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007328 (IS_SCHEMA(child, "group")) ||
7329 (IS_SCHEMA(child, "any")) ||
7330 (IS_SCHEMA(child, "choice")) ||
7331 (IS_SCHEMA(child, "sequence"))) {
7332 subtype = NULL;
7333 if (IS_SCHEMA(child, "element")) {
7334 subtype = (xmlSchemaTypePtr)
7335 xmlSchemaParseElement(ctxt, schema, child, 0);
7336 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007337 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007338 } else if (IS_SCHEMA(child, "any")) {
7339 subtype = xmlSchemaParseAny(ctxt, schema, child);
7340 } else if (IS_SCHEMA(child, "sequence")) {
7341 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7342 } else if (IS_SCHEMA(child, "choice")) {
7343 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7344 }
7345 if (subtype != NULL) {
7346 if (last == NULL) {
7347 type->subtypes = subtype;
7348 last = subtype;
7349 } else {
7350 last->next = subtype;
7351 last = subtype;
7352 }
7353 last->next = NULL;
7354 }
7355 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007356 }
7357 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007358 /* TODO: error code. */
7359 xmlSchemaPContentErr(ctxt,
7360 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7361 NULL, type, node, child, NULL,
7362 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007363 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007364 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007365 return (type);
7366}
7367
7368/**
7369 * xmlSchemaParseSequence:
7370 * @ctxt: a schema validation context
7371 * @schema: the schema being built
7372 * @node: a subtree containing XML Schema informations
7373 *
7374 * parse a XML schema Sequence definition
7375 * *WARNING* this interface is highly subject to change
7376 *
William M. Bracke7091952004-05-11 15:09:58 +00007377 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007378 * 1 in case of success.
7379 */
7380static xmlSchemaTypePtr
7381xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007382 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007383{
7384 xmlSchemaTypePtr type, subtype, last = NULL;
7385 xmlNodePtr child = NULL;
7386 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007387 xmlAttrPtr attr;
7388 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007389
7390 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7391 return (NULL);
7392
William M. Brack2f2a6632004-08-20 23:09:47 +00007393 oldcontainer = ctxt->container;
7394 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7395 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007396 if (type == NULL)
7397 return (NULL);
7398 type->node = node;
7399 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007400 /*
7401 * Check for illegal attributes.
7402 */
7403 attr = node->properties;
7404 while (attr != NULL) {
7405 if (attr->ns == NULL) {
7406 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7407 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7408 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7409 xmlSchemaPIllegalAttrErr(ctxt,
7410 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7411 NULL, type, attr);
7412 }
7413 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7414 xmlSchemaPIllegalAttrErr(ctxt,
7415 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7416 NULL, type, attr);
7417 }
7418 attr = attr->next;
7419 }
7420 /*
7421 * Extract and validate attributes.
7422 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007423 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007424 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7425 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7426 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007427 /*
7428 * And now for the children...
7429 */
7430 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007431 child = node->children;
7432 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007433 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7434 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007435 }
7436 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007437 (IS_SCHEMA(child, "group")) ||
7438 (IS_SCHEMA(child, "any")) ||
7439 (IS_SCHEMA(child, "choice")) ||
7440 (IS_SCHEMA(child, "sequence"))) {
7441 subtype = NULL;
7442 if (IS_SCHEMA(child, "element")) {
7443 subtype = (xmlSchemaTypePtr)
7444 xmlSchemaParseElement(ctxt, schema, child, 0);
7445 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007446 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007447 } else if (IS_SCHEMA(child, "any")) {
7448 subtype = xmlSchemaParseAny(ctxt, schema, child);
7449 } else if (IS_SCHEMA(child, "choice")) {
7450 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7451 } else if (IS_SCHEMA(child, "sequence")) {
7452 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7453 }
7454 if (subtype != NULL) {
7455 if (last == NULL) {
7456 type->subtypes = subtype;
7457 last = subtype;
7458 } else {
7459 last->next = subtype;
7460 last = subtype;
7461 }
7462 last->next = NULL;
7463 }
7464 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007465 }
7466 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007467 xmlSchemaPContentErr(ctxt,
7468 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7469 NULL, type, node, child, NULL,
7470 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007471 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007472 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007473
7474 return (type);
7475}
7476
7477/**
7478 * xmlSchemaParseRestriction:
7479 * @ctxt: a schema validation context
7480 * @schema: the schema being built
7481 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007482 *
7483 * parse a XML schema Restriction definition
7484 * *WARNING* this interface is highly subject to change
7485 *
7486 * Returns the type definition or NULL in case of error
7487 */
7488static xmlSchemaTypePtr
7489xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007490 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007491{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007492 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007493 xmlNodePtr child = NULL;
7494 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007495 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007496 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007497
7498 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7499 return (NULL);
7500
7501 oldcontainer = ctxt->container;
7502
William M. Brack2f2a6632004-08-20 23:09:47 +00007503 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7504 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007505 if (type == NULL)
7506 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007507 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007508 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007509 /*
7510 * Check for illegal attributes.
7511 */
7512 attr = node->properties;
7513 while (attr != NULL) {
7514 if (attr->ns == NULL) {
7515 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7516 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7517 xmlSchemaPIllegalAttrErr(ctxt,
7518 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7519 NULL, type, attr);
7520 }
7521 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7522 xmlSchemaPIllegalAttrErr(ctxt,
7523 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7524 NULL, type, attr);
7525 }
7526 attr = attr->next;
7527 }
7528 /*
7529 * Extract and validate attributes.
7530 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007531 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007532 /*
7533 * Attribute "base".
7534 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007535 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007536 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007537 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7538 /* TODO: Think about the error code. */
7539 xmlSchemaPMissingAttrErr(ctxt,
7540 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7541 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007542 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007543 /*
7544 * And now for the children...
7545 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007546 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007547 child = node->children;
7548 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007549 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7550 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007551 }
7552 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007553 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7554 if (IS_SCHEMA(child, "all")) {
7555 subtype = (xmlSchemaTypePtr)
7556 xmlSchemaParseAll(ctxt, schema, child);
7557 child = child->next;
7558 type->subtypes = subtype;
7559 } else if (IS_SCHEMA(child, "choice")) {
7560 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7561 child = child->next;
7562 type->subtypes = subtype;
7563 } else if (IS_SCHEMA(child, "sequence")) {
7564 subtype = (xmlSchemaTypePtr)
7565 xmlSchemaParseSequence(ctxt, schema, child);
7566 child = child->next;
7567 type->subtypes = subtype;
7568 } else if (IS_SCHEMA(child, "group")) {
7569 subtype = (xmlSchemaTypePtr)
7570 xmlSchemaParseGroup(ctxt, schema, child, 0);
7571 child = child->next;
7572 type->subtypes = subtype;
7573 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007574 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7575 if (IS_SCHEMA(child, "simpleType")) {
7576 if (type->base != NULL) {
7577 /*
7578 * src-restriction-base-or-simpleType
7579 * Either the base [attribute] or the simpleType [child] of the
7580 * <restriction> element must be present, but not both.
7581 */
7582 xmlSchemaPContentErr(ctxt,
7583 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7584 NULL, NULL, type->node, child,
7585 "The attribute 'base' and the <simpleType> child are "
7586 "mutually exclusive", NULL);
7587 } else {
7588 subtype = (xmlSchemaTypePtr)
7589 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7590 type->baseType = subtype;
7591 }
7592 child = child->next;
7593 }
7594 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007595 if (IS_SCHEMA(child, "simpleType")) {
7596 subtype = (xmlSchemaTypePtr)
7597 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007598 type->subtypes = subtype;
7599 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007600 }
7601 }
7602 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7603 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7604 xmlSchemaFacetPtr facet, lastfacet = NULL;
7605
Daniel Veillard01fa6152004-06-29 17:04:39 +00007606 /*
7607 * Add the facets to the parent simpleType/complexType.
7608 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007609 /*
7610 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7611 * Simple Type Definition Schema Representation Constraint:
7612 * *Single Facet Value*
7613 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007614 while ((IS_SCHEMA(child, "minInclusive")) ||
7615 (IS_SCHEMA(child, "minExclusive")) ||
7616 (IS_SCHEMA(child, "maxInclusive")) ||
7617 (IS_SCHEMA(child, "maxExclusive")) ||
7618 (IS_SCHEMA(child, "totalDigits")) ||
7619 (IS_SCHEMA(child, "fractionDigits")) ||
7620 (IS_SCHEMA(child, "pattern")) ||
7621 (IS_SCHEMA(child, "enumeration")) ||
7622 (IS_SCHEMA(child, "whiteSpace")) ||
7623 (IS_SCHEMA(child, "length")) ||
7624 (IS_SCHEMA(child, "maxLength")) ||
7625 (IS_SCHEMA(child, "minLength"))) {
7626 facet = xmlSchemaParseFacet(ctxt, schema, child);
7627 if (facet != NULL) {
7628 if (lastfacet == NULL)
7629 ctxt->ctxtType->facets = facet;
7630 else
7631 lastfacet->next = facet;
7632 lastfacet = facet;
7633 lastfacet->next = NULL;
7634 }
7635 child = child->next;
7636 }
7637 /*
7638 * Create links for derivation and validation.
7639 */
7640 if (lastfacet != NULL) {
7641 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7642
7643 facet = ctxt->ctxtType->facets;
7644 do {
7645 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7646 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007647 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007648 xmlFree(facetLink);
7649 return (NULL);
7650 }
7651 facetLink->facet = facet;
7652 facetLink->next = NULL;
7653 if (lastFacetLink == NULL)
7654 ctxt->ctxtType->facetSet = facetLink;
7655 else
7656 lastFacetLink->next = facetLink;
7657 lastFacetLink = facetLink;
7658 facet = facet->next;
7659 } while (facet != NULL);
7660 }
7661 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007662 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7663 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7664 if (IS_SCHEMA(child, "anyAttribute")) {
7665 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7666 child = child->next;
7667 }
7668 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007669 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007670 /* TODO: Think about the error code. */
7671 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7672 xmlSchemaPContentErr(ctxt,
7673 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7674 NULL, type, node, child, NULL,
7675 "annotation?, (group | all | choice | sequence)?, "
7676 "((attribute | attributeGroup)*, anyAttribute?))");
7677 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7678 xmlSchemaPContentErr(ctxt,
7679 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7680 NULL, type, node, child, NULL,
7681 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7682 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7683 "length | minLength | maxLength | enumeration | whiteSpace | "
7684 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7685 } else {
7686 /* Simple type */
7687 xmlSchemaPContentErr(ctxt,
7688 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7689 NULL, type, node, child, NULL,
7690 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7691 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7692 "length | minLength | maxLength | enumeration | whiteSpace | "
7693 "pattern)*))");
7694 }
7695 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007696 ctxt->container = oldcontainer;
7697 return (type);
7698}
7699
7700/**
7701 * xmlSchemaParseExtension:
7702 * @ctxt: a schema validation context
7703 * @schema: the schema being built
7704 * @node: a subtree containing XML Schema informations
7705 *
7706 * parse a XML schema Extension definition
7707 * *WARNING* this interface is highly subject to change
7708 *
7709 * Returns the type definition or NULL in case of error
7710 */
7711static xmlSchemaTypePtr
7712xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007713 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007714{
7715 xmlSchemaTypePtr type, subtype;
7716 xmlNodePtr child = NULL;
7717 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007718 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007719
7720 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7721 return (NULL);
7722
7723 oldcontainer = ctxt->container;
7724
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007725 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007726 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007727 if (type == NULL)
7728 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007729 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007730 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007731 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007732 ctxt->container = name;
7733
7734 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7735 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007736 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007737 "<extension>: The attribute \"base\" is missing.\n",
7738 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007739 }
7740 child = node->children;
7741 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007742 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7743 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007744 }
7745 subtype = NULL;
7746
7747 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007748 subtype = xmlSchemaParseAll(ctxt, schema, child);
7749 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007750 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007751 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7752 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007753 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007754 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7755 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007756 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007757 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007758 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007759 }
7760 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007761 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007762 if ((ctxt->ctxtType != NULL) &&
7763 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7764 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7765 if (IS_SCHEMA(child, "anyAttribute")) {
7766 ctxt->ctxtType->attributeWildcard =
7767 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7768 child = child->next;
7769 }
7770 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007771 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007772 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007773 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7774 "<extension> has unexpected content.\n", type->name,
7775 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007776 }
7777 ctxt->container = oldcontainer;
7778 return (type);
7779}
7780
7781/**
7782 * xmlSchemaParseSimpleContent:
7783 * @ctxt: a schema validation context
7784 * @schema: the schema being built
7785 * @node: a subtree containing XML Schema informations
7786 *
7787 * parse a XML schema SimpleContent definition
7788 * *WARNING* this interface is highly subject to change
7789 *
7790 * Returns the type definition or NULL in case of error
7791 */
7792static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007793xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7794 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007795{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007796 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007797 xmlNodePtr child = NULL;
7798 xmlChar name[30];
7799
7800 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7801 return (NULL);
7802
William M. Bracke7091952004-05-11 15:09:58 +00007803 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007804 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007805 if (type == NULL)
7806 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007807 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007808 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007809 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007810
7811 child = node->children;
7812 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007813 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7814 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007815 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007816 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007817 ctxt->parentItem = type;
7818 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007819 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007820 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007821 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007822 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007823 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007824 subtype = (xmlSchemaTypePtr)
7825 xmlSchemaParseExtension(ctxt, schema, child);
7826 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007827 }
7828 type->subtypes = subtype;
7829 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007830 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007831 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7832 "<simpleContent> has unexpected content.\n",
7833 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007834 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007835 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007836 return (type);
7837}
7838
7839/**
7840 * xmlSchemaParseComplexContent:
7841 * @ctxt: a schema validation context
7842 * @schema: the schema being built
7843 * @node: a subtree containing XML Schema informations
7844 *
7845 * parse a XML schema ComplexContent definition
7846 * *WARNING* this interface is highly subject to change
7847 *
7848 * Returns the type definition or NULL in case of error
7849 */
7850static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007851xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7852 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007853{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007854 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007855 xmlNodePtr child = NULL;
7856 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007857 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007858
7859 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7860 return (NULL);
7861
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007862 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007863 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007864 if (type == NULL)
7865 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007866 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007867 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007868 /*
7869 * Check for illegal attributes.
7870 */
7871 attr = node->properties;
7872 while (attr != NULL) {
7873 if (attr->ns == NULL) {
7874 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7875 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7876 {
7877 xmlSchemaPIllegalAttrErr(ctxt,
7878 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7879 NULL, NULL, attr);
7880 }
7881 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7882 xmlSchemaPIllegalAttrErr(ctxt,
7883 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7884 NULL, NULL, attr);
7885 }
7886 attr = attr->next;
7887 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007888 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007889 /*
7890 * Handle attribute 'mixed'.
7891 */
7892 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7893 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7894 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7895 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007896 child = node->children;
7897 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007898 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7899 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007900 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007901 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007902 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007903 subtype = NULL;
7904 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007905 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007906 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007907 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007908 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007909 subtype = (xmlSchemaTypePtr)
7910 xmlSchemaParseExtension(ctxt, schema, child);
7911 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007912 }
7913 type->subtypes = subtype;
7914 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007915 xmlSchemaPContentErr(ctxt,
7916 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7917 NULL, NULL, node, child,
7918 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007919 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007920 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007921 return (type);
7922}
7923
7924/**
7925 * xmlSchemaParseComplexType:
7926 * @ctxt: a schema validation context
7927 * @schema: the schema being built
7928 * @node: a subtree containing XML Schema informations
7929 *
7930 * parse a XML schema Complex Type definition
7931 * *WARNING* this interface is highly subject to change
7932 *
7933 * Returns the type definition or NULL in case of error
7934 */
7935static xmlSchemaTypePtr
7936xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007937 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007938{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007939 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007940 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007941 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007942 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007943 xmlAttrPtr attr;
7944 const xmlChar *attrValue;
7945 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007946 char buf[40];
7947
Daniel Veillard4255d502002-04-16 15:50:10 +00007948
7949 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7950 return (NULL);
7951
Daniel Veillard01fa6152004-06-29 17:04:39 +00007952 ctxtType = ctxt->ctxtType;
7953
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007954 if (topLevel) {
7955 attr = xmlSchemaGetPropNode(node, "name");
7956 if (attr == NULL) {
7957 xmlSchemaPMissingAttrErr(ctxt,
7958 XML_SCHEMAP_S4S_ATTR_MISSING,
7959 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7960 "name", NULL);
7961 return (NULL);
7962 } else if (xmlSchemaPValAttrNode(ctxt,
7963 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7964 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7965 return (NULL);
7966 }
7967 }
7968
7969 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007970 /*
7971 * Parse as local complex type definition.
7972 */
7973 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7974 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7975 if (type == NULL)
7976 return (NULL);
7977 name = (const xmlChar *) buf;
7978 type->node = node;
7979 type->type = XML_SCHEMA_TYPE_COMPLEX;
7980 /*
7981 * TODO: We need the target namespace.
7982 */
7983 } else {
7984 /*
7985 * Parse as global complex type definition.
7986 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007987 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007988 if (type == NULL)
7989 return (NULL);
7990 type->node = node;
7991 type->type = XML_SCHEMA_TYPE_COMPLEX;
7992 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7993 /*
7994 * Set defaults.
7995 */
7996 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7997 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
7998 }
7999 /*
8000 * Handle attributes.
8001 */
8002 attr = node->properties;
8003 while (attr != NULL) {
8004 if (attr->ns == NULL) {
8005 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8006 /*
8007 * Attribute "id".
8008 */
8009 type->id = xmlSchemaGetProp(ctxt, node, "id");
8010 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8011 /*
8012 * Attribute "mixed".
8013 */
8014 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8015 (xmlNodePtr) attr))
8016 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8017 } else if (topLevel) {
8018 /*
8019 * Attributes of global complex type definitions.
8020 */
8021 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8022 /* Pass. */
8023 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8024 /*
8025 * Attribute "abstract".
8026 */
8027 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8028 (xmlNodePtr) attr))
8029 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8030 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8031 /*
8032 * Attribute "final".
8033 */
8034 attrValue = xmlSchemaGetNodeContent(ctxt,
8035 (xmlNodePtr) attr);
8036 if (xmlSchemaPValAttrBlockFinal(attrValue,
8037 &(type->flags),
8038 -1,
8039 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8040 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8041 -1, -1, -1) != 0)
8042 {
8043 xmlSchemaPSimpleTypeErr(ctxt,
8044 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8045 &des, type, (xmlNodePtr) attr,
8046 NULL,
8047 "(#all | List of (extension | restriction))",
8048 attrValue, NULL, NULL, NULL);
8049 }
8050 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8051 /*
8052 * Attribute "block".
8053 */
8054 attrValue = xmlSchemaGetNodeContent(ctxt,
8055 (xmlNodePtr) attr);
8056 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8057 -1,
8058 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8059 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8060 -1, -1, -1) != 0) {
8061 xmlSchemaPSimpleTypeErr(ctxt,
8062 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8063 &des, type, (xmlNodePtr) attr,
8064 NULL,
8065 "(#all | List of (extension | restriction)) ",
8066 attrValue, NULL, NULL, NULL);
8067 }
8068 } else {
8069 xmlSchemaPIllegalAttrErr(ctxt,
8070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8071 &des, type, attr);
8072 }
8073 } else {
8074 xmlSchemaPIllegalAttrErr(ctxt,
8075 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8076 &des, type, attr);
8077 }
8078 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8079 xmlSchemaPIllegalAttrErr(ctxt,
8080 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8081 &des, type, attr);
8082 }
8083 attr = attr->next;
8084 }
8085 /*
8086 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008087 * This will be only changed if a complex type
8088 * inherits an attribute wildcard from a base type.
8089 */
8090 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008091 /*
8092 * And now for the children...
8093 */
8094 oldcontainer = ctxt->container;
8095 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008096 child = node->children;
8097 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008098 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8099 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008100 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008101 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008102 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008103 /*
8104 * 3.4.3 : 2.2
8105 * Specifying mixed='true' when the <simpleContent>
8106 * alternative is chosen has no effect
8107 */
William M. Bracke7091952004-05-11 15:09:58 +00008108 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8109 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008110 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8111 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008112 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008113 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8114 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008115 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008116 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008117 /*
8118 * Parse model groups.
8119 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008120 if (IS_SCHEMA(child, "all")) {
8121 subtype = xmlSchemaParseAll(ctxt, schema, child);
8122 child = child->next;
8123 } else if (IS_SCHEMA(child, "choice")) {
8124 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8125 child = child->next;
8126 } else if (IS_SCHEMA(child, "sequence")) {
8127 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8128 child = child->next;
8129 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008130 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008131 child = child->next;
8132 }
8133 if (subtype != NULL)
8134 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008135 /*
8136 * Parse attribute decls/refs.
8137 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008138 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008139 /*
8140 * Parse attribute wildcard.
8141 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008142 if (IS_SCHEMA(child, "anyAttribute")) {
8143 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8144 child = child->next;
8145 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008146 }
8147 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008148 xmlSchemaPContentErr(ctxt,
8149 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8150 &des, type, node, child,
8151 NULL, "(annotation?, (simpleContent | complexContent | "
8152 "((group | all | choice | sequence)?, ((attribute | "
8153 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008154 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008155 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008156 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008157 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008158 return (type);
8159}
8160
Daniel Veillard4255d502002-04-16 15:50:10 +00008161/**
8162 * xmlSchemaParseSchema:
8163 * @ctxt: a schema validation context
8164 * @node: a subtree containing XML Schema informations
8165 *
8166 * parse a XML schema definition from a node set
8167 * *WARNING* this interface is highly subject to change
8168 *
8169 * Returns the internal XML Schema structure built from the resource or
8170 * NULL in case of error
8171 */
8172static xmlSchemaPtr
8173xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8174{
8175 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008176 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008177 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008179
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008180 /*
8181 * This one is called by xmlSchemaParse only and is used if
8182 * the schema to be parsed was specified via the API; i.e. not
8183 * automatically by the validated instance document.
8184 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008185 if ((ctxt == NULL) || (node == NULL))
8186 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008187 nberrors = ctxt->nberrors;
8188 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008189 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008190 xmlSchemaImportPtr import;
8191
Daniel Veillard4255d502002-04-16 15:50:10 +00008192 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008193 if (schema == NULL)
8194 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008195 /*
8196 * Disable build of list of items.
8197 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008198 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8199 if (attr != NULL) {
8200 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8201 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8202 /*
8203 * TODO: Should we proceed with an invalid target namespace?
8204 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008205 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8206 } else {
8207 schema->targetNamespace = NULL;
8208 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008209 /*
8210 * Add the current ns name and location to the import table;
8211 * this is needed to have a consistent mechanism, regardless
8212 * if all schemata are constructed dynamically fired by the
8213 * instance or if the schema to be used was specified via
8214 * the API.
8215 */
8216 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8217 schema->targetNamespace);
8218 if (import == NULL) {
8219 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8220 NULL, NULL, (xmlNodePtr) ctxt->doc,
8221 "Internal error: xmlSchemaParseSchema, "
8222 "failed to add an import entry", NULL);
8223 xmlSchemaFree(schema);
8224 schema = NULL;
8225 return (NULL);
8226 }
8227 import->schemaLocation = ctxt->URL;
8228 /*
8229 * NOTE: We won't set the doc here, otherwise it will be freed
8230 * if the import struct is freed.
8231 * import->doc = ctxt->doc;
8232 */
8233
Daniel Veillardc0826a72004-08-10 14:17:33 +00008234 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008235 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008236 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8237 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8238
William M. Brack2f2a6632004-08-20 23:09:47 +00008239 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008240 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8241 } else {
8242 xmlDocPtr doc;
8243
8244 doc = node->doc;
8245
8246 if ((doc != NULL) && (doc->URL != NULL)) {
8247 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8248 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008249 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008250 } else {
8251 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8252 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008253 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008254 }
8255 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008256 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008257 if (ctxt->nberrors != 0) {
8258 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008259 xmlSchemaFree(schema);
8260 schema = NULL;
8261 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008262 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008263 if (schema != NULL)
8264 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008265 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008266#ifdef DEBUG
8267 if (schema == NULL)
8268 xmlGenericError(xmlGenericErrorContext,
8269 "xmlSchemaParse() failed\n");
8270#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008271 return (schema);
8272}
8273
8274/************************************************************************
8275 * *
8276 * Validating using Schemas *
8277 * *
8278 ************************************************************************/
8279
8280/************************************************************************
8281 * *
8282 * Reading/Writing Schemas *
8283 * *
8284 ************************************************************************/
8285
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008286#if 0 /* Will be enabled if it is clear what options are needed. */
8287/**
8288 * xmlSchemaParserCtxtSetOptions:
8289 * @ctxt: a schema parser context
8290 * @options: a combination of xmlSchemaParserOption
8291 *
8292 * Sets the options to be used during the parse.
8293 *
8294 * Returns 0 in case of success, -1 in case of an
8295 * API error.
8296 */
8297static int
8298xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8299 int options)
8300
8301{
8302 int i;
8303
8304 if (ctxt == NULL)
8305 return (-1);
8306 /*
8307 * WARNING: Change the start value if adding to the
8308 * xmlSchemaParseOption.
8309 */
8310 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8311 if (options & 1<<i) {
8312 return (-1);
8313 }
8314 }
8315 ctxt->options = options;
8316 return (0);
8317}
8318
8319/**
8320 * xmlSchemaValidCtxtGetOptions:
8321 * @ctxt: a schema parser context
8322 *
8323 * Returns the option combination of the parser context.
8324 */
8325static int
8326xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8327
8328{
8329 if (ctxt == NULL)
8330 return (-1);
8331 else
8332 return (ctxt->options);
8333}
8334
8335 void *curItems; /* used for dynamic addition of schemata */
8336 int nbCurItems; /* used for dynamic addition of schemata */
8337 int sizeCurItems; /* used for dynamic addition of schemata */
8338
8339#endif
8340
Daniel Veillard4255d502002-04-16 15:50:10 +00008341/**
8342 * xmlSchemaNewParserCtxt:
8343 * @URL: the location of the schema
8344 *
8345 * Create an XML Schemas parse context for that file/resource expected
8346 * to contain an XML Schemas file.
8347 *
8348 * Returns the parser context or NULL in case of error
8349 */
8350xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008351xmlSchemaNewParserCtxt(const char *URL)
8352{
Daniel Veillard4255d502002-04-16 15:50:10 +00008353 xmlSchemaParserCtxtPtr ret;
8354
8355 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008356 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008357
8358 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8359 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008360 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008361 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008362 return (NULL);
8363 }
8364 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008365 ret->dict = xmlDictCreate();
8366 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008367 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008368 return (ret);
8369}
8370
8371/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008372 * xmlSchemaNewParserCtxtUseDict:
8373 * @URL: the location of the schema
8374 * @dict: the dictionary to be used
8375 *
8376 * Create an XML Schemas parse context for that file/resource expected
8377 * to contain an XML Schemas file.
8378 *
8379 * Returns the parser context or NULL in case of error
8380 */
8381static xmlSchemaParserCtxtPtr
8382xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8383{
8384 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008385 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008386 if (URL == NULL)
8387 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008388 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008389
8390 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8391 if (ret == NULL) {
8392 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8393 NULL);
8394 return (NULL);
8395 }
8396 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8397 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008398 xmlDictReference(dict);
8399 if (URL != NULL)
8400 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008401 ret->includes = 0;
8402 return (ret);
8403}
8404
8405
8406/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008407 * xmlSchemaNewMemParserCtxt:
8408 * @buffer: a pointer to a char array containing the schemas
8409 * @size: the size of the array
8410 *
8411 * Create an XML Schemas parse context for that memory buffer expected
8412 * to contain an XML Schemas file.
8413 *
8414 * Returns the parser context or NULL in case of error
8415 */
8416xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008417xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8418{
Daniel Veillard6045c902002-10-09 21:13:59 +00008419 xmlSchemaParserCtxtPtr ret;
8420
8421 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008422 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008423
8424 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8425 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008426 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008427 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008428 return (NULL);
8429 }
8430 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8431 ret->buffer = buffer;
8432 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008433 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008434 return (ret);
8435}
8436
8437/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008438 * xmlSchemaNewDocParserCtxt:
8439 * @doc: a preparsed document tree
8440 *
8441 * Create an XML Schemas parse context for that document.
8442 * NB. The document may be modified during the parsing process.
8443 *
8444 * Returns the parser context or NULL in case of error
8445 */
8446xmlSchemaParserCtxtPtr
8447xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8448{
8449 xmlSchemaParserCtxtPtr ret;
8450
8451 if (doc == NULL)
8452 return (NULL);
8453
8454 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8455 if (ret == NULL) {
8456 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8457 NULL);
8458 return (NULL);
8459 }
8460 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8461 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008462 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008463 /* The application has responsibility for the document */
8464 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008465
8466 return (ret);
8467}
8468
8469/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008470 * xmlSchemaFreeParserCtxt:
8471 * @ctxt: the schema parser context
8472 *
8473 * Free the resources associated to the schema parser context
8474 */
8475void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008476xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8477{
Daniel Veillard4255d502002-04-16 15:50:10 +00008478 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008479 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008480 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008481 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008482 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008483 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008484 xmlFree(ctxt->assemble);
8485 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008486 if (ctxt->vctxt != NULL) {
8487 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8488 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008489 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008490 xmlFree(ctxt);
8491}
8492
8493/************************************************************************
8494 * *
8495 * Building the content models *
8496 * *
8497 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008498
Daniel Veillard4255d502002-04-16 15:50:10 +00008499/**
8500 * xmlSchemaBuildAContentModel:
8501 * @type: the schema type definition
8502 * @ctxt: the schema parser context
8503 * @name: the element name whose content is being built
8504 *
8505 * Generate the automata sequence needed for that type
8506 */
8507static void
8508xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008509 xmlSchemaParserCtxtPtr ctxt,
8510 const xmlChar * name)
8511{
Daniel Veillard4255d502002-04-16 15:50:10 +00008512 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008513 xmlGenericError(xmlGenericErrorContext,
8514 "Found unexpected type = NULL in %s content model\n",
8515 name);
8516 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008517 }
8518 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008519 case XML_SCHEMA_TYPE_ANY: {
8520 xmlAutomataStatePtr start, end;
8521 xmlSchemaWildcardPtr wild;
8522 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008523
Daniel Veillardc0826a72004-08-10 14:17:33 +00008524 wild = type->attributeWildcard;
8525
8526 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008527 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008528 "Internal error: xmlSchemaBuildAContentModel, "
8529 "no wildcard on xsd:any.\n", NULL, NULL);
8530 return;
8531 }
8532
8533 start = ctxt->state;
8534 end = xmlAutomataNewState(ctxt->am);
8535
8536 if (type->maxOccurs == 1) {
8537 if (wild->any == 1) {
8538 /*
8539 * We need to add both transitions:
8540 *
8541 * 1. the {"*", "*"} for elements in a namespace.
8542 */
8543 ctxt->state =
8544 xmlAutomataNewTransition2(ctxt->am,
8545 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8546 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8547 /*
8548 * 2. the {"*"} for elements in no namespace.
8549 */
8550 ctxt->state =
8551 xmlAutomataNewTransition2(ctxt->am,
8552 start, NULL, BAD_CAST "*", NULL, type);
8553 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8554
8555 } else if (wild->nsSet != NULL) {
8556 ns = wild->nsSet;
8557 do {
8558 ctxt->state = start;
8559 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8560 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8561 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8562 ns = ns->next;
8563 } while (ns != NULL);
8564
8565 } else if (wild->negNsSet != NULL) {
8566 xmlAutomataStatePtr deadEnd;
8567
8568 deadEnd = xmlAutomataNewState(ctxt->am);
8569 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8570 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8571 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8572 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8573 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8574 }
8575 } else {
8576 int counter;
8577 xmlAutomataStatePtr hop;
8578 int maxOccurs =
8579 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8580 int minOccurs =
8581 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8582
8583 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8584 hop = xmlAutomataNewState(ctxt->am);
8585 if (wild->any == 1) {
8586 ctxt->state =
8587 xmlAutomataNewTransition2(ctxt->am,
8588 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8589 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8590 ctxt->state =
8591 xmlAutomataNewTransition2(ctxt->am,
8592 start, NULL, BAD_CAST "*", NULL, type);
8593 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8594 } else if (wild->nsSet != NULL) {
8595 ns = wild->nsSet;
8596 do {
8597 ctxt->state =
8598 xmlAutomataNewTransition2(ctxt->am,
8599 start, NULL, BAD_CAST "*", ns->value, type);
8600 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8601 ns = ns->next;
8602 } while (ns != NULL);
8603
8604 } else if (wild->negNsSet != NULL) {
8605 xmlAutomataStatePtr deadEnd;
8606
8607 deadEnd = xmlAutomataNewState(ctxt->am);
8608 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8609 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8610 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8611 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8612 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8613 }
8614 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8615 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8616 }
8617 if (type->minOccurs == 0) {
8618 xmlAutomataNewEpsilon(ctxt->am, start, end);
8619 }
8620 ctxt->state = end;
8621 break;
8622 }
8623 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008624 xmlAutomataStatePtr oldstate;
8625 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008626
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008627 /*
8628 * IMPORTANT: This puts element declarations
8629 * (and never element decl. references) into the
8630 * automaton. This is crucial and should not be changed,
8631 * since validating functions rely now on it.
8632 */
8633 particle = (xmlSchemaElementPtr) type;
8634 if (particle->ref != NULL) {
8635 if (particle->refDecl == NULL) {
8636 /*
8637 * Skip content model creation if the reference
8638 * did not resolve to a declaration.
8639 */
8640 break;
8641 } else {
8642 /*
8643 * Referenced global element declaration.
8644 */
8645 elemDecl = particle->refDecl;
8646 }
8647 } else {
8648 /*
8649 * Anonymous element declaration.
8650 */
8651 elemDecl = particle;
8652 }
8653
8654 oldstate = ctxt->state;
8655
8656 if (particle->maxOccurs >= UNBOUNDED) {
8657 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008658 xmlAutomataStatePtr tmp;
8659 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008660
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008661 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008662 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008663 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008664 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008665 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00008666 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008667 xmlAutomataNewTransition2(ctxt->am,
8668 ctxt->state, NULL,
8669 elemDecl->name,
8670 elemDecl->targetNamespace,
8671 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008672 tmp = ctxt->state;
8673 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008674 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008675 ctxt->state =
8676 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008677 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008678
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008679 } else {
8680 ctxt->state =
8681 xmlAutomataNewTransition2(ctxt->am,
8682 ctxt->state, NULL,
8683 elemDecl->name,
8684 elemDecl->targetNamespace,
8685 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008686 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8687 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008688 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008689 /* basically an elem* */
8690 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8691 ctxt->state);
8692 }
8693 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008694 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008695 xmlAutomataStatePtr tmp;
8696 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008697
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008698 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8699 oldstate, NULL);
8700 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008701 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008702 particle->minOccurs - 1,
8703 particle->maxOccurs - 1);
8704 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8705 ctxt->state,
8706 NULL,
8707 elemDecl->name,
8708 elemDecl->targetNamespace,
8709 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008710 tmp = ctxt->state;
8711 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008712 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008713 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008714 NULL, counter);
8715 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008716 /* basically an elem? */
8717 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008718 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008719 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008720
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008721 } else {
8722 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8723 ctxt->state,
8724 NULL,
8725 elemDecl->name,
8726 elemDecl->targetNamespace,
8727 (xmlSchemaTypePtr) elemDecl);
8728 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008729 /* basically an elem? */
8730 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008731 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008732 }
8733 }
8734 break;
8735 }
8736 case XML_SCHEMA_TYPE_SEQUENCE:{
8737 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008738
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008739 /*
8740 * If max and min occurances are default (1) then
8741 * simply iterate over the subtypes
8742 */
8743 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8744 subtypes = type->subtypes;
8745 while (subtypes != NULL) {
8746 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8747 subtypes = subtypes->next;
8748 }
8749 } else {
8750 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008751
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008752 if (type->maxOccurs >= UNBOUNDED) {
8753 if (type->minOccurs > 1) {
8754 xmlAutomataStatePtr tmp;
8755 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008756
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008757 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8758 oldstate,
8759 NULL);
8760 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008761
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008762 counter = xmlAutomataNewCounter(ctxt->am,
8763 type->
8764 minOccurs - 1,
8765 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008766
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008767 subtypes = type->subtypes;
8768 while (subtypes != NULL) {
8769 xmlSchemaBuildAContentModel(subtypes, ctxt,
8770 name);
8771 subtypes = subtypes->next;
8772 }
8773 tmp = ctxt->state;
8774 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8775 oldstate, counter);
8776 ctxt->state =
8777 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8778 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008779
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008780 } else {
8781 subtypes = type->subtypes;
8782 while (subtypes != NULL) {
8783 xmlSchemaBuildAContentModel(subtypes, ctxt,
8784 name);
8785 subtypes = subtypes->next;
8786 }
8787 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8788 oldstate);
8789 if (type->minOccurs == 0) {
8790 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8791 ctxt->state);
8792 }
8793 }
8794 } else if ((type->maxOccurs > 1)
8795 || (type->minOccurs > 1)) {
8796 xmlAutomataStatePtr tmp;
8797 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008798
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008799 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8800 oldstate,
8801 NULL);
8802 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008803
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008804 counter = xmlAutomataNewCounter(ctxt->am,
8805 type->minOccurs -
8806 1,
8807 type->maxOccurs -
8808 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008809
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008810 subtypes = type->subtypes;
8811 while (subtypes != NULL) {
8812 xmlSchemaBuildAContentModel(subtypes, ctxt,
8813 name);
8814 subtypes = subtypes->next;
8815 }
8816 tmp = ctxt->state;
8817 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8818 counter);
8819 ctxt->state =
8820 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8821 counter);
8822 if (type->minOccurs == 0) {
8823 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8824 ctxt->state);
8825 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008826
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008827 } else {
8828 subtypes = type->subtypes;
8829 while (subtypes != NULL) {
8830 xmlSchemaBuildAContentModel(subtypes, ctxt,
8831 name);
8832 subtypes = subtypes->next;
8833 }
8834 if (type->minOccurs == 0) {
8835 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8836 ctxt->state);
8837 }
8838 }
8839 }
8840 break;
8841 }
8842 case XML_SCHEMA_TYPE_CHOICE:{
8843 xmlSchemaTypePtr subtypes;
8844 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008845
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008846 start = ctxt->state;
8847 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008848
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008849 /*
8850 * iterate over the subtypes and remerge the end with an
8851 * epsilon transition
8852 */
8853 if (type->maxOccurs == 1) {
8854 subtypes = type->subtypes;
8855 while (subtypes != NULL) {
8856 ctxt->state = start;
8857 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8858 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8859 subtypes = subtypes->next;
8860 }
8861 } else {
8862 int counter;
8863 xmlAutomataStatePtr hop;
8864 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8865 UNBOUNDED : type->maxOccurs - 1;
8866 int minOccurs =
8867 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008868
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008869 /*
8870 * use a counter to keep track of the number of transtions
8871 * which went through the choice.
8872 */
8873 counter =
8874 xmlAutomataNewCounter(ctxt->am, minOccurs,
8875 maxOccurs);
8876 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008877
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008878 subtypes = type->subtypes;
8879 while (subtypes != NULL) {
8880 ctxt->state = start;
8881 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8882 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8883 subtypes = subtypes->next;
8884 }
8885 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8886 counter);
8887 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8888 counter);
8889 }
8890 if (type->minOccurs == 0) {
8891 xmlAutomataNewEpsilon(ctxt->am, start, end);
8892 }
8893 ctxt->state = end;
8894 break;
8895 }
8896 case XML_SCHEMA_TYPE_ALL:{
8897 xmlAutomataStatePtr start;
8898 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008899
Daniel Veillard3646d642004-06-02 19:19:14 +00008900 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008901 int lax;
8902
8903 subtypes = type->subtypes;
8904 if (subtypes == NULL)
8905 break;
8906 start = ctxt->state;
8907 while (subtypes != NULL) {
8908 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008909 /*
8910 * the following 'if' was needed to fix bug 139897
8911 * not quite sure why it only needs to be done for
8912 * elements with a 'ref', but it seems to work ok.
8913 */
8914 if (subtypes->ref != NULL)
8915 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008916 elem = (xmlSchemaElementPtr) subtypes;
8917 /*
8918 * NOTE: The {max occurs} of all the particles in the
8919 * {particles} of the group must be 0 or 1.
8920 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008921 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008922 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8923 ctxt->state,
8924 elem->name,
8925 elem->targetNamespace,
8926 1, 1, subtypes);
8927 } else if ((elem->minOccurs == 0) &&
8928 (elem->maxOccurs == 1)) {
8929
8930 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8931 ctxt->state,
8932 elem->name,
8933 elem->targetNamespace,
8934 0,
8935 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008936 subtypes);
8937 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008938 /*
8939 * NOTE: if maxOccurs == 0 then no transition will be
8940 * created.
8941 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008942 subtypes = subtypes->next;
8943 }
8944 lax = type->minOccurs == 0;
8945 ctxt->state =
8946 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8947 lax);
8948 break;
8949 }
8950 case XML_SCHEMA_TYPE_RESTRICTION:
8951 if (type->subtypes != NULL)
8952 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8953 break;
8954 case XML_SCHEMA_TYPE_EXTENSION:
8955 if (type->baseType != NULL) {
8956 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008957
8958 /*
8959 * TODO: Circular definitions will be checked at the
8960 * constraint level. So remove this when the complex type
8961 * constraints are implemented.
8962 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008963 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008964 /* TODO: Change the error code. */
8965 xmlSchemaPCustomErr(ctxt,
8966 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8967 NULL, type, type->node,
8968 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008969 return;
8970 }
8971 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008972 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008973 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008974 subtypes = type->subtypes;
8975 while (subtypes != NULL) {
8976 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8977 subtypes = subtypes->next;
8978 }
8979 } else if (type->subtypes != NULL)
8980 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8981 break;
8982 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008983 /*
8984 * Handle model group definition references.
8985 * NOTE: type->subtypes is the referenced model grop definition;
8986 * and type->subtypes->subtypes is the model group (i.e. <all> or
8987 * <choice> or <sequence>).
8988 */
8989 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8990 (type->subtypes->subtypes != NULL)) {
8991 xmlSchemaTypePtr modelGr;
8992 xmlAutomataStatePtr start, end;
8993
8994 modelGr = type->subtypes->subtypes;
8995 start = ctxt->state;
8996 end = xmlAutomataNewState(ctxt->am);
8997 if (type->maxOccurs == 1) {
8998 ctxt->state = start;
8999 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9000 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9001 } else {
9002 int counter;
9003 xmlAutomataStatePtr hop;
9004 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9005 UNBOUNDED : type->maxOccurs - 1;
9006 int minOccurs =
9007 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9008
9009 counter =
9010 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9011 hop = xmlAutomataNewState(ctxt->am);
9012 ctxt->state = start;
9013 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9014 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9015 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9016 counter);
9017 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9018 counter);
9019 }
9020 if (type->minOccurs == 0) {
9021 xmlAutomataNewEpsilon(ctxt->am, start, end);
9022 }
9023 ctxt->state = end;
9024 break;
9025 }
9026 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009027 case XML_SCHEMA_TYPE_COMPLEX:
9028 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9029 if (type->subtypes != NULL)
9030 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9031 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009032 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9033 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009034 default:
9035 xmlGenericError(xmlGenericErrorContext,
9036 "Found unexpected type %d in %s content model\n",
9037 type->type, name);
9038 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009039 }
9040}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009041
Daniel Veillard4255d502002-04-16 15:50:10 +00009042/**
9043 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009044 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009045 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009046 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009047 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009048 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009049 */
9050static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009051xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009052 xmlSchemaParserCtxtPtr ctxt,
9053 const xmlChar * name)
9054{
Daniel Veillard4255d502002-04-16 15:50:10 +00009055 xmlAutomataStatePtr start;
9056
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009057 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9058 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9059 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9060 (type->contModel != NULL))
9061 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009062
9063#ifdef DEBUG_CONTENT
9064 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009065 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009066#endif
9067
Daniel Veillard4255d502002-04-16 15:50:10 +00009068 ctxt->am = xmlNewAutomata();
9069 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009070 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009071 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009072 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009073 }
9074 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009075 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009076 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009077 type->contModel = xmlAutomataCompile(ctxt->am);
9078 if (type->contModel == NULL) {
9079 xmlSchemaPCustomErr(ctxt,
9080 XML_SCHEMAP_INTERNAL,
9081 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009082 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009083 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009084 xmlSchemaPCustomErr(ctxt,
9085 XML_SCHEMAP_NOT_DETERMINISTIC,
9086 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009087 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009088 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009089 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009090#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009091 xmlGenericError(xmlGenericErrorContext,
9092 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009093 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009094#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009095 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009096 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009097 xmlFreeAutomata(ctxt->am);
9098 ctxt->am = NULL;
9099}
9100
9101/**
9102 * xmlSchemaRefFixupCallback:
9103 * @elem: the schema element context
9104 * @ctxt: the schema parser context
9105 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009106 * Resolves the references of an element declaration
9107 * or particle, which has an element declaration as it's
9108 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009109 */
9110static void
9111xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009112 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009113 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009114 const xmlChar * context ATTRIBUTE_UNUSED,
9115 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009116{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009117 if ((ctxt == NULL) || (elem == NULL) ||
9118 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009119 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009120 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009121 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009122 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009123
Daniel Veillardc0826a72004-08-10 14:17:33 +00009124 /*
9125 * TODO: Evaluate, what errors could occur if the declaration is not
9126 * found. It might be possible that the "typefixup" might crash if
9127 * no ref declaration was found.
9128 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009129 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009130 if (elemDecl == NULL) {
9131 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009132 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009133 NULL, (xmlSchemaTypePtr) elem, elem->node,
9134 "ref", elem->ref, elem->refNs,
9135 XML_SCHEMA_TYPE_ELEMENT, NULL);
9136 } else
9137 elem->refDecl = elemDecl;
9138 } else {
9139 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9140 xmlSchemaTypePtr type;
9141
9142 /* (type definition) ... otherwise the type definition ·resolved·
9143 * to by the ·actual value· of the type [attribute] ...
9144 */
9145 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9146 elem->namedTypeNs);
9147 if (type == NULL) {
9148 xmlSchemaPResCompAttrErr(ctxt,
9149 XML_SCHEMAP_SRC_RESOLVE,
9150 NULL, (xmlSchemaTypePtr) elem, elem->node,
9151 "type", elem->namedType, elem->namedTypeNs,
9152 XML_SCHEMA_TYPE_BASIC, "type definition");
9153 } else
9154 elem->subtypes = type;
9155 }
9156 if (elem->substGroup != NULL) {
9157 xmlSchemaElementPtr substHead;
9158
9159 /*
9160 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9161 * substitutionGroup?
9162 */
9163 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009164 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009165 if (substHead == NULL) {
9166 xmlSchemaPResCompAttrErr(ctxt,
9167 XML_SCHEMAP_SRC_RESOLVE,
9168 NULL, (xmlSchemaTypePtr) elem, NULL,
9169 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9170 XML_SCHEMA_TYPE_ELEMENT, NULL);
9171 } else {
9172 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9173 /*
9174 * (type definition)...otherwise the {type definition} of the
9175 * element declaration ·resolved· to by the ·actual value· of
9176 * the substitutionGroup [attribute], if present
9177 */
9178 if (elem->subtypes == NULL)
9179 elem->subtypes = substHead->subtypes;
9180 }
9181 }
9182 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9183 (elem->substGroup == NULL))
9184 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9185 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009186}
9187
William M. Bracke7091952004-05-11 15:09:58 +00009188/**
9189 * xmlSchemaParseListRefFixup:
9190 * @type: the schema type definition
9191 * @ctxt: the schema parser context
9192 *
9193 * Fixup of the itemType reference of the list type.
9194 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009195static void
William M. Bracke7091952004-05-11 15:09:58 +00009196xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009197{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009198
Daniel Veillard01fa6152004-06-29 17:04:39 +00009199 if (((type->base == NULL) &&
9200 (type->subtypes == NULL)) ||
9201 ((type->base != NULL) &&
9202 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009203 /*
9204 * src-list-itemType-or-simpleType
9205 * Either the itemType [attribute] or the <simpleType> [child] of
9206 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009207 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009208 /*
9209 * TODO: Move this to the parse function.
9210 */
9211 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009212 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009213 NULL, type, type->node,
9214 "The attribute 'itemType' and the <simpleType> child "
9215 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009216 } else if (type->base!= NULL) {
9217 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9218 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009219 xmlSchemaPResCompAttrErr(ctxt,
9220 XML_SCHEMAP_SRC_RESOLVE,
9221 NULL, type, type->node,
9222 "itemType", type->base, type->baseNs,
9223 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009224 }
9225 }
9226 if ((type->subtypes != NULL) &&
9227 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9228 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009229}
9230
9231/**
9232 * xmlSchemaParseUnionRefCheck:
9233 * @typeDecl: the schema type definition
9234 * @ctxt: the schema parser context
9235 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009236 * Checks and builds the memberTypes of the union type.
9237 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009238 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009239static int
William M. Bracke7091952004-05-11 15:09:58 +00009240xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009241 xmlSchemaParserCtxtPtr ctxt)
9242{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009243
Daniel Veillard01fa6152004-06-29 17:04:39 +00009244 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9245 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009246
Daniel Veillard01fa6152004-06-29 17:04:39 +00009247 /* 1 If the <union> alternative is chosen, then [Definition:]
9248 * define the explicit members as the type definitions ·resolved·
9249 * to by the items in the ·actual value· of the memberTypes [attribute],
9250 * if any, followed by the type definitions corresponding to the
9251 * <simpleType>s among the [children] of <union>, if any.
9252 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009253
Daniel Veillard01fa6152004-06-29 17:04:39 +00009254 if (type->type != XML_SCHEMA_TYPE_UNION)
9255 return (-1);
9256 if (ctxt->ctxtType == NULL) {
9257 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009258 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009259 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9260 "available", NULL, NULL);
9261 return (-1);
9262 }
9263 /*
9264 * src-union-memberTypes-or-simpleTypes
9265 * Either the memberTypes [attribute] of the <union> element must
9266 * be non-empty or there must be at least one simpleType [child].
9267 */
9268 if ((type->base == NULL) &&
9269 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009270 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009271 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009272 NULL, NULL, type->node,
9273 "Either the attribute 'memberTypes' must be non-empty "
9274 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009275 }
9276
9277 ctxtType = ctxt->ctxtType;
9278 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009279 xmlAttrPtr attr;
9280 const xmlChar *cur, *end;
9281 xmlChar *tmp;
9282 const xmlChar *localName, *uri;
9283
9284 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009285 cur = type->base;
9286 do {
9287 while (IS_BLANK_CH(*cur))
9288 cur++;
9289 end = cur;
9290 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9291 end++;
9292 if (end == cur)
9293 break;
9294 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009295 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9296 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9297 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009298 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009299 xmlSchemaPResCompAttrErr(ctxt,
9300 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9301 NULL, NULL, type->node, "memberTypes", localName, uri,
9302 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009303 } else {
9304 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9305 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9306 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9307 if (link == NULL) {
9308 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9309 return (-1);
9310 }
9311 link->type = memberType;
9312 link->next = NULL;
9313 if (lastLink == NULL)
9314 ctxtType->memberTypes = link;
9315 else
9316 lastLink->next = link;
9317 lastLink = link;
9318 }
9319 xmlFree(tmp);
9320 cur = end;
9321 } while (*cur != 0);
9322 }
9323 /*
9324 * Add local simple types,
9325 */
9326 memberType = type->subtypes;
9327 while (memberType != NULL) {
9328 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9329 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9330 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9331 if (link == NULL) {
9332 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9333 return (-1);
9334 }
9335 link->type = memberType;
9336 link->next = NULL;
9337 if (lastLink == NULL)
9338 ctxtType->memberTypes = link;
9339 else
9340 lastLink->next = link;
9341 lastLink = link;
9342 memberType = memberType->next;
9343 }
9344 /*
9345 * The actual value is then formed by replacing any union type
9346 * definition in the ·explicit members· with the members of their
9347 * {member type definitions}, in order.
9348 */
9349 link = ctxtType->memberTypes;
9350 while (link != NULL) {
9351 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9352 subLink = link->type->memberTypes;
9353 if (subLink != NULL) {
9354 link->type = subLink->type;
9355 if (subLink->next != NULL) {
9356 lastLink = link->next;
9357 subLink = subLink->next;
9358 prevLink = link;
9359 while (subLink != NULL) {
9360 newLink = (xmlSchemaTypeLinkPtr)
9361 xmlMalloc(sizeof(xmlSchemaTypeLink));
9362 if (newLink == NULL) {
9363 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9364 NULL);
9365 return (-1);
9366 }
9367 newLink->type = memberType;
9368 prevLink->next = newLink;
9369 prevLink = newLink;
9370 newLink->next = lastLink;
9371
9372 subLink = subLink->next;
9373 }
9374 }
9375 }
9376 }
9377 link = link->next;
9378 }
9379
9380 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009381}
9382
Daniel Veillard4255d502002-04-16 15:50:10 +00009383/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009384 * xmlSchemaIsDerivedFromBuiltInType:
9385 * @ctxt: the schema parser context
9386 * @type: the type definition
9387 * @valType: the value type
9388 *
9389 *
9390 * Returns 1 if the type has the given value type, or
9391 * is derived from such a type.
9392 */
William M. Brack803812b2004-06-03 02:11:24 +00009393static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009394xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9395 xmlSchemaTypePtr type, int valType)
9396{
9397 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009398 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009399 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009400 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009401 return(1);
9402 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9403 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9404 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9405 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9406 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9407 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9408 if (type->baseType != NULL)
9409 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9410 valType));
9411 } else if ((type->subtypes != NULL) &&
9412 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9413 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9414 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9415 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9416 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9417 valType));
9418 }
9419
9420 return (0);
9421}
9422
9423/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009424 * xmlSchemaIsDerivedFromBuiltInType:
9425 * @type: the simpleType definition
9426 *
9427 * Returns the primitive type of the given type or
9428 * NULL in case of error.
9429 */
9430static xmlSchemaTypePtr
9431xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9432{
9433 while (type != NULL) {
9434 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9435 return (type);
9436 type = type->baseType;
9437 }
9438
9439 return (NULL);
9440}
9441
9442
9443/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009444 * xmlSchemaBuildAttributeUsesOwned:
9445 * @ctxt: the schema parser context
9446 * @type: the complex type definition
9447 * @cur: the attribute declaration list
9448 * @lastUse: the top of the attribute use list
9449 *
9450 * Builds the attribute uses list on the given complex type.
9451 * This one is supposed to be called by
9452 * xmlSchemaBuildAttributeValidation only.
9453 */
9454static int
9455xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9456 xmlSchemaAttributePtr cur,
9457 xmlSchemaAttributeLinkPtr *uses,
9458 xmlSchemaAttributeLinkPtr *lastUse)
9459{
9460 xmlSchemaAttributeLinkPtr tmp;
9461 while (cur != NULL) {
9462 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9463 /*
9464 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9465 * to by the ·actual value·s of the ref [attribute] of the
9466 * <attributeGroup> [children], if any."
9467 */
9468 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9469 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9470 lastUse) == -1) {
9471 return (-1);
9472 }
9473 } else {
9474 /* W3C: "1 The set of attribute uses corresponding to the
9475 * <attribute> [children], if any."
9476 */
9477 tmp = (xmlSchemaAttributeLinkPtr)
9478 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9479 if (tmp == NULL) {
9480 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9481 return (-1);
9482 }
9483 tmp->attr = cur;
9484 tmp->next = NULL;
9485 if (*uses == NULL)
9486 *uses = tmp;
9487 else
9488 (*lastUse)->next = tmp;
9489 *lastUse = tmp;
9490 }
9491 cur = cur->next;
9492 }
9493 return (0);
9494}
9495
Daniel Veillard50355f02004-06-08 17:52:16 +00009496/**
9497 * xmlSchemaCloneWildcardNsConstraints:
9498 * @ctxt: the schema parser context
9499 * @dest: the destination wildcard
9500 * @source: the source wildcard
9501 *
9502 * Clones the namespace constraints of source
9503 * and assignes them to dest.
9504 * Returns -1 on internal error, 0 otherwise.
9505 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009506static int
9507xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9508 xmlSchemaWildcardPtr *dest,
9509 xmlSchemaWildcardPtr source)
9510{
9511 xmlSchemaWildcardNsPtr cur, tmp, last;
9512
9513 if ((source == NULL) || (*dest == NULL))
9514 return(-1);
9515 (*dest)->any = source->any;
9516 cur = source->nsSet;
9517 last = NULL;
9518 while (cur != NULL) {
9519 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9520 if (tmp == NULL)
9521 return(-1);
9522 tmp->value = cur->value;
9523 if (last == NULL)
9524 (*dest)->nsSet = tmp;
9525 else
9526 last->next = tmp;
9527 last = tmp;
9528 cur = cur->next;
9529 }
9530 if ((*dest)->negNsSet != NULL)
9531 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9532 if (source->negNsSet != NULL) {
9533 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9534 if ((*dest)->negNsSet == NULL)
9535 return(-1);
9536 (*dest)->negNsSet->value = source->negNsSet->value;
9537 } else
9538 (*dest)->negNsSet = NULL;
9539 return(0);
9540}
9541
Daniel Veillard50355f02004-06-08 17:52:16 +00009542/**
9543 * xmlSchemaUnionWildcards:
9544 * @ctxt: the schema parser context
9545 * @completeWild: the first wildcard
9546 * @curWild: the second wildcard
9547 *
9548 * Unions the namespace constraints of the given wildcards.
9549 * @completeWild will hold the resulting union.
9550 * Returns a positive error code on failure, -1 in case of an
9551 * internal error, 0 otherwise.
9552 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009553static int
9554xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9555 xmlSchemaWildcardPtr completeWild,
9556 xmlSchemaWildcardPtr curWild)
9557{
9558 xmlSchemaWildcardNsPtr cur, curB, tmp;
9559
9560 /*
9561 * 1 If O1 and O2 are the same value, then that value must be the
9562 * value.
9563 */
9564 if ((completeWild->any == curWild->any) &&
9565 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9566 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9567
9568 if ((completeWild->negNsSet == NULL) ||
9569 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9570
9571 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009572 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009573
9574 /*
9575 * Check equality of sets.
9576 */
9577 cur = completeWild->nsSet;
9578 while (cur != NULL) {
9579 found = 0;
9580 curB = curWild->nsSet;
9581 while (curB != NULL) {
9582 if (cur->value == curB->value) {
9583 found = 1;
9584 break;
9585 }
9586 curB = curB->next;
9587 }
9588 if (!found)
9589 break;
9590 cur = cur->next;
9591 }
9592 if (found)
9593 return(0);
9594 } else
9595 return(0);
9596 }
9597 }
9598 /*
9599 * 2 If either O1 or O2 is any, then any must be the value
9600 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009601 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009602 if (completeWild->any == 0) {
9603 completeWild->any = 1;
9604 if (completeWild->nsSet != NULL) {
9605 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9606 completeWild->nsSet = NULL;
9607 }
9608 if (completeWild->negNsSet != NULL) {
9609 xmlFree(completeWild->negNsSet);
9610 completeWild->negNsSet = NULL;
9611 }
9612 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009613 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009614 }
9615 /*
9616 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9617 * then the union of those sets must be the value.
9618 */
9619 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9620 int found;
9621 xmlSchemaWildcardNsPtr start;
9622
9623 cur = curWild->nsSet;
9624 start = completeWild->nsSet;
9625 while (cur != NULL) {
9626 found = 0;
9627 curB = start;
9628 while (curB != NULL) {
9629 if (cur->value == curB->value) {
9630 found = 1;
9631 break;
9632 }
9633 curB = curB->next;
9634 }
9635 if (!found) {
9636 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9637 if (tmp == NULL)
9638 return (-1);
9639 tmp->value = cur->value;
9640 tmp->next = completeWild->nsSet;
9641 completeWild->nsSet = tmp;
9642 }
9643 cur = cur->next;
9644 }
9645
9646 return(0);
9647 }
9648 /*
9649 * 4 If the two are negations of different values (namespace names
9650 * or ·absent·), then a pair of not and ·absent· must be the value.
9651 */
9652 if ((completeWild->negNsSet != NULL) &&
9653 (curWild->negNsSet != NULL) &&
9654 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9655 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009656
9657 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009658 }
9659 /*
9660 * 5.
9661 */
9662 if (((completeWild->negNsSet != NULL) &&
9663 (completeWild->negNsSet->value != NULL) &&
9664 (curWild->nsSet != NULL)) ||
9665 ((curWild->negNsSet != NULL) &&
9666 (curWild->negNsSet->value != NULL) &&
9667 (completeWild->nsSet != NULL))) {
9668
9669 int nsFound, absentFound = 0;
9670
9671 if (completeWild->nsSet != NULL) {
9672 cur = completeWild->nsSet;
9673 curB = curWild->negNsSet;
9674 } else {
9675 cur = curWild->nsSet;
9676 curB = completeWild->negNsSet;
9677 }
9678 nsFound = 0;
9679 while (cur != NULL) {
9680 if (cur->value == NULL)
9681 absentFound = 1;
9682 else if (cur->value == curB->value)
9683 nsFound = 1;
9684 if (nsFound && absentFound)
9685 break;
9686 cur = cur->next;
9687 }
9688
9689 if (nsFound && absentFound) {
9690 /*
9691 * 5.1 If the set S includes both the negated namespace
9692 * name and ·absent·, then any must be the value.
9693 */
9694 completeWild->any = 1;
9695 if (completeWild->nsSet != NULL) {
9696 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9697 completeWild->nsSet = NULL;
9698 }
9699 if (completeWild->negNsSet != NULL) {
9700 xmlFree(completeWild->negNsSet);
9701 completeWild->negNsSet = NULL;
9702 }
9703 } else if (nsFound && (!absentFound)) {
9704 /*
9705 * 5.2 If the set S includes the negated namespace name
9706 * but not ·absent·, then a pair of not and ·absent· must
9707 * be the value.
9708 */
9709 if (completeWild->nsSet != NULL) {
9710 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9711 completeWild->nsSet = NULL;
9712 }
9713 if (completeWild->negNsSet == NULL) {
9714 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9715 if (completeWild->negNsSet == NULL)
9716 return (-1);
9717 }
9718 completeWild->negNsSet->value = NULL;
9719 } else if ((!nsFound) && absentFound) {
9720 /*
9721 * 5.3 If the set S includes ·absent· but not the negated
9722 * namespace name, then the union is not expressible.
9723 */
9724 xmlSchemaPErr(ctxt, completeWild->node,
9725 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009726 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009727 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009728 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009729 } else if ((!nsFound) && (!absentFound)) {
9730 /*
9731 * 5.4 If the set S does not include either the negated namespace
9732 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9733 * and a namespace name must be the value.
9734 */
9735 if (completeWild->negNsSet == NULL) {
9736 if (completeWild->nsSet != NULL) {
9737 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9738 completeWild->nsSet = NULL;
9739 }
9740 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9741 if (completeWild->negNsSet == NULL)
9742 return (-1);
9743 completeWild->negNsSet->value = curWild->negNsSet->value;
9744 }
9745 }
9746 return (0);
9747 }
9748 /*
9749 * 6.
9750 */
9751 if (((completeWild->negNsSet != NULL) &&
9752 (completeWild->negNsSet->value == NULL) &&
9753 (curWild->nsSet != NULL)) ||
9754 ((curWild->negNsSet != NULL) &&
9755 (curWild->negNsSet->value == NULL) &&
9756 (completeWild->nsSet != NULL))) {
9757
9758 if (completeWild->nsSet != NULL) {
9759 cur = completeWild->nsSet;
9760 } else {
9761 cur = curWild->nsSet;
9762 }
9763 while (cur != NULL) {
9764 if (cur->value == NULL) {
9765 /*
9766 * 6.1 If the set S includes ·absent·, then any must be the
9767 * value.
9768 */
9769 completeWild->any = 1;
9770 if (completeWild->nsSet != NULL) {
9771 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9772 completeWild->nsSet = NULL;
9773 }
9774 if (completeWild->negNsSet != NULL) {
9775 xmlFree(completeWild->negNsSet);
9776 completeWild->negNsSet = NULL;
9777 }
9778 return (0);
9779 }
9780 cur = cur->next;
9781 }
9782 if (completeWild->negNsSet == NULL) {
9783 /*
9784 * 6.2 If the set S does not include ·absent·, then a pair of not
9785 * and ·absent· must be the value.
9786 */
9787 if (completeWild->nsSet != NULL) {
9788 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9789 completeWild->nsSet = NULL;
9790 }
9791 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9792 if (completeWild->negNsSet == NULL)
9793 return (-1);
9794 completeWild->negNsSet->value = NULL;
9795 }
9796 return (0);
9797 }
9798 return (0);
9799
9800}
9801
Daniel Veillard50355f02004-06-08 17:52:16 +00009802/**
9803 * xmlSchemaIntersectWildcards:
9804 * @ctxt: the schema parser context
9805 * @completeWild: the first wildcard
9806 * @curWild: the second wildcard
9807 *
9808 * Intersects the namespace constraints of the given wildcards.
9809 * @completeWild will hold the resulting intersection.
9810 * Returns a positive error code on failure, -1 in case of an
9811 * internal error, 0 otherwise.
9812 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009813static int
9814xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9815 xmlSchemaWildcardPtr completeWild,
9816 xmlSchemaWildcardPtr curWild)
9817{
William M. Brack803812b2004-06-03 02:11:24 +00009818 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009819
9820 /*
9821 * 1 If O1 and O2 are the same value, then that value must be the
9822 * value.
9823 */
9824 if ((completeWild->any == curWild->any) &&
9825 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9826 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9827
9828 if ((completeWild->negNsSet == NULL) ||
9829 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9830
9831 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009832 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009833
9834 /*
9835 * Check equality of sets.
9836 */
9837 cur = completeWild->nsSet;
9838 while (cur != NULL) {
9839 found = 0;
9840 curB = curWild->nsSet;
9841 while (curB != NULL) {
9842 if (cur->value == curB->value) {
9843 found = 1;
9844 break;
9845 }
9846 curB = curB->next;
9847 }
9848 if (!found)
9849 break;
9850 cur = cur->next;
9851 }
9852 if (found)
9853 return(0);
9854 } else
9855 return(0);
9856 }
9857 }
9858 /*
9859 * 2 If either O1 or O2 is any, then the other must be the value.
9860 */
9861 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9862 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9863 return(-1);
9864 return(0);
9865 }
9866 /*
9867 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9868 * name or ·absent·) and the other is a set of (namespace names or
9869 * ·absent·), then that set, minus the negated value if it was in
9870 * the set, minus ·absent· if it was in the set, must be the value.
9871 */
9872 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9873 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9874 const xmlChar *neg;
9875
9876 if (completeWild->nsSet == NULL) {
9877 neg = completeWild->negNsSet->value;
9878 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9879 return(-1);
9880 } else
9881 neg = curWild->negNsSet->value;
9882 /*
9883 * Remove absent and negated.
9884 */
9885 prev = NULL;
9886 cur = completeWild->nsSet;
9887 while (cur != NULL) {
9888 if (cur->value == NULL) {
9889 if (prev == NULL)
9890 completeWild->nsSet = cur->next;
9891 else
9892 prev->next = cur->next;
9893 xmlFree(cur);
9894 break;
9895 }
9896 prev = cur;
9897 cur = cur->next;
9898 }
9899 if (neg != NULL) {
9900 prev = NULL;
9901 cur = completeWild->nsSet;
9902 while (cur != NULL) {
9903 if (cur->value == neg) {
9904 if (prev == NULL)
9905 completeWild->nsSet = cur->next;
9906 else
9907 prev->next = cur->next;
9908 xmlFree(cur);
9909 break;
9910 }
9911 prev = cur;
9912 cur = cur->next;
9913 }
9914 }
9915
9916 return(0);
9917 }
9918 /*
9919 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9920 * then the intersection of those sets must be the value.
9921 */
9922 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9923 int found;
9924
9925 cur = completeWild->nsSet;
9926 prev = NULL;
9927 while (cur != NULL) {
9928 found = 0;
9929 curB = curWild->nsSet;
9930 while (curB != NULL) {
9931 if (cur->value == curB->value) {
9932 found = 1;
9933 break;
9934 }
9935 curB = curB->next;
9936 }
9937 if (!found) {
9938 if (prev == NULL)
9939 completeWild->nsSet = cur->next;
9940 else
9941 prev->next = cur->next;
9942 tmp = cur->next;
9943 xmlFree(cur);
9944 cur = tmp;
9945 continue;
9946 }
9947 prev = cur;
9948 cur = cur->next;
9949 }
9950
9951 return(0);
9952 }
9953 /* 5 If the two are negations of different namespace names,
9954 * then the intersection is not expressible
9955 */
9956 if ((completeWild->negNsSet != NULL) &&
9957 (curWild->negNsSet != NULL) &&
9958 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9959 (completeWild->negNsSet->value != NULL) &&
9960 (curWild->negNsSet->value != NULL)) {
9961
9962 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009963 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009964 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009965 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009966 }
9967 /*
9968 * 6 If the one is a negation of a namespace name and the other
9969 * is a negation of ·absent·, then the one which is the negation
9970 * of a namespace name must be the value.
9971 */
9972 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9973 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9974 (completeWild->negNsSet->value == NULL)) {
9975 completeWild->negNsSet->value = curWild->negNsSet->value;
9976 }
9977 return(0);
9978}
9979
Daniel Veillard50355f02004-06-08 17:52:16 +00009980/**
9981 * xmlSchemaIsWildcardNsConstraintSubset:
9982 * @ctxt: the schema parser context
9983 * @wildA: the first wildcard
9984 * @wildB: the second wildcard
9985 *
9986 * Returns 1 if the namespace constraint of @wildA is an intensional
9987 * subset of @wildB, 0 otherwise.
9988 */
9989static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009990xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9991 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009992{
Daniel Veillard3646d642004-06-02 19:19:14 +00009993
Daniel Veillard50355f02004-06-08 17:52:16 +00009994 /*
9995 * Schema Component Constraint: Wildcard Subset
9996 */
9997 /*
9998 * 1 super must be any.
9999 */
10000 if (wildB->any)
10001 return (1);
10002 /*
10003 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10004 * 2.2 super must be a pair of not and the same value.
10005 */
10006 if ((wildA->negNsSet != NULL) &&
10007 (wildB->negNsSet != NULL) &&
10008 (wildA->negNsSet->value == wildA->negNsSet->value))
10009 return (1);
10010 /*
10011 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10012 */
10013 if (wildA->nsSet != NULL) {
10014 /*
10015 * 3.2.1 super must be the same set or a superset thereof.
10016 */
10017 if (wildB->nsSet != NULL) {
10018 xmlSchemaWildcardNsPtr cur, curB;
10019 int found = 0;
10020
10021 cur = wildA->nsSet;
10022 while (cur != NULL) {
10023 found = 0;
10024 curB = wildB->nsSet;
10025 while (curB != NULL) {
10026 if (cur->value == curB->value) {
10027 found = 1;
10028 break;
10029 }
10030 curB = curB->next;
10031 }
10032 if (!found)
10033 return (0);
10034 cur = cur->next;
10035 }
10036 if (found)
10037 return (1);
10038 } else if (wildB->negNsSet != NULL) {
10039 xmlSchemaWildcardNsPtr cur;
10040 /*
10041 * 3.2.2 super must be a pair of not and a namespace name or
10042 * ·absent· and that value must not be in sub's set.
10043 */
10044 cur = wildA->nsSet;
10045 while (cur != NULL) {
10046 if (cur->value == wildB->negNsSet->value)
10047 return (0);
10048 cur = cur->next;
10049 }
10050 return (1);
10051 }
10052 }
10053 return (0);
10054}
10055
10056/**
10057 * xmlSchemaBuildCompleteAttributeWildcard:
10058 * @ctxt: the schema parser context
10059 * @attrs: the attribute list
10060 * @completeWild: the resulting complete wildcard
10061 *
10062 * Returns -1 in case of an internal error, 0 otherwise.
10063 */
10064static int
10065xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10066 xmlSchemaAttributePtr attrs,
10067 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010068{
10069 while (attrs != NULL) {
10070 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10071 xmlSchemaAttributeGroupPtr group;
10072
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010073 group = (xmlSchemaAttributeGroupPtr) attrs;
10074 /*
10075 * Handle attribute group references.
10076 */
10077 if (group->ref != NULL) {
10078 if (group->refItem == NULL) {
10079 /*
10080 * TODO: Should we raise a warning here?
10081 */
10082 /*
10083 * The referenced attribute group definition could not
10084 * be resolved beforehand, so skip.
10085 */
10086 attrs = attrs->next;
10087 continue;
10088 } else
10089 group = group->refItem;
10090 }
10091 /*
10092 * For every attribute group definition, an intersected wildcard
10093 * will be created (assumed that a wildcard exists on the
10094 * particular attr. gr. def. or on any contained attr. gr. def
10095 * at all).
10096 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10097 * that the intersection will be performed only once.
10098 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010099 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10100 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010101 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10102 group->attributes, &group->attributeWildcard) == -1)
10103 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010104 }
10105 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10106 }
10107 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010108 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010109 /*
10110 * Copy the first encountered wildcard as context, except for the annotation.
10111 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010112 *completeWild = xmlSchemaAddWildcard(ctxt);
10113 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10114 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10115 completeWild, group->attributeWildcard) == -1)
10116 return (-1);
10117 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010118 /*
10119 * Although the complete wildcard might not correspond to any
10120 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010121 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010122 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010123 (*completeWild)->node = group->attributeWildcard->node;
10124
10125 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10126 xmlSchemaFreeWildcard(*completeWild);
10127 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010128 }
10129 }
10130 }
10131 attrs = attrs->next;
10132 }
10133
Daniel Veillard50355f02004-06-08 17:52:16 +000010134 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010135}
10136
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010137static int
10138xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10139 int *fixed,
10140 const xmlChar **value,
10141 xmlSchemaValPtr *val)
10142{
10143 *fixed = 0;
10144 *value = NULL;
10145 if (val != 0)
10146 *val = NULL;
10147
10148 if (item->defValue == NULL)
10149 item = item->refDecl;
10150
10151 if (item == NULL)
10152 return (0);
10153
10154 if (item->defValue != NULL) {
10155 *value = item->defValue;
10156 if (val != 0)
10157 *val = item->defVal;
10158 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10159 *fixed = 1;
10160 return (1);
10161 }
10162 return (0);
10163}
Daniel Veillard3646d642004-06-02 19:19:14 +000010164/**
10165 * xmlSchemaMatchesWildcardNs:
10166 * @wild: the wildcard
10167 * @ns: the namespace
10168 *
10169 *
10170 * Returns 1 if the given namespace matches the wildcard,
10171 * 0 otherwise.
10172 */
10173static int
10174xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10175{
10176 if (wild == NULL)
10177 return(0);
10178
10179 if (wild->any)
10180 return(1);
10181 else if (wild->nsSet != NULL) {
10182 xmlSchemaWildcardNsPtr cur;
10183
10184 cur = wild->nsSet;
10185 while (cur != NULL) {
10186 if (xmlStrEqual(cur->value, ns))
10187 return(1);
10188 cur = cur->next;
10189 }
10190 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10191 (!xmlStrEqual(wild->negNsSet->value, ns)))
10192 return(1);
10193
10194 return(0);
10195}
10196
10197/**
10198 * xmlSchemaBuildAttributeValidation:
10199 * @ctxt: the schema parser context
10200 * @type: the complex type definition
10201 *
10202 *
10203 * Builds the wildcard and the attribute uses on the given complex type.
10204 * Returns -1 if an internal error occurs, 0 otherwise.
10205 */
10206static int
10207xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10208{
10209 xmlSchemaTypePtr baseType = NULL;
10210 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010211 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010212 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010213 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010214 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010215 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010216 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010217
Daniel Veillard01fa6152004-06-29 17:04:39 +000010218 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010219 /*
10220 * Complex Type Definition with complex content Schema Component.
10221 *
10222 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010223 * TODO: Add checks for absent referenced attribute declarations and
10224 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010225 */
10226 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010227 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010228 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010229 "attribute uses already builded.\n",
10230 NULL, NULL);
10231 return (-1);
10232 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010233 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010234 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010235 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010236 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010237 type->name, NULL);
10238 return (-1);
10239 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010240 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010241 if (baseType == anyType)
10242 baseIsAnyType = 1;
10243 /*
10244 * Inherit the attribute uses of the base type.
10245 */
10246 /*
10247 * NOTE: It is allowed to "extend" the anyType complex type.
10248 */
10249 if (!baseIsAnyType) {
10250 if (baseType != NULL) {
10251 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10252 tmp = (xmlSchemaAttributeLinkPtr)
10253 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10254 if (tmp == NULL) {
10255 xmlSchemaPErrMemory(ctxt,
10256 "building attribute uses of complexType", NULL);
10257 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010258 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010259 tmp->attr = cur->attr;
10260 tmp->next = NULL;
10261 if (type->attributeUses == NULL) {
10262 type->attributeUses = tmp;
10263 } else
10264 lastBaseUse->next = tmp;
10265 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010266 }
10267 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010268 }
10269 if ((type->subtypes != NULL) &&
10270 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10271 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010272 /*
10273 * type --> (<simpleContent>|<complexContent>)
10274 * --> (<restriction>|<extension>) --> attributes
10275 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010276 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010277 } else {
10278 /* Short hand form of the complexType. */
10279 attrs = type->attributes;
10280 }
10281 /*
10282 * Handle attribute wildcards.
10283 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010284 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10285 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010286 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010287 * NOTE: During the parse time, the wildcard is created on the complexType
10288 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010289 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010290 if (err == -1) {
10291 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10292 "Internal error: xmlSchemaBuildAttributeValidation: "
10293 "failed to build an intersected attribute wildcard.\n",
10294 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010295 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010296 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010297
10298 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10299 ((baseIsAnyType) ||
10300 ((baseType != NULL) &&
10301 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10302 (baseType->attributeWildcard != NULL)))) {
10303 if (type->attributeWildcard != NULL) {
10304 /*
10305 * Union the complete wildcard with the base wildcard.
10306 */
10307 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10308 baseType->attributeWildcard) == -1)
10309 return (-1);
10310 } else {
10311 /*
10312 * Just inherit the wildcard.
10313 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010314 /*
10315 * NOTE: This is the only case where an attribute
10316 * wildcard is shared.
10317 */
10318 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10319 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010320 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010321 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010322 }
10323
10324 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10325 if (type->attributeWildcard != NULL) {
10326 /*
10327 * Derivation Valid (Restriction, Complex)
10328 * 4.1 The {base type definition} must also have one.
10329 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010330 if (baseType->attributeWildcard == NULL) {
10331 xmlSchemaPCustomErr(ctxt,
10332 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10333 NULL, type, NULL,
10334 "The type has an attribute wildcard, "
10335 "but the base type %s does not have one",
10336 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10337 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010338 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010339 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010340 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10341 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010342 xmlSchemaPCustomErr(ctxt,
10343 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10344 NULL, type, NULL,
10345 "The attribute wildcard is not a valid "
10346 "subset of the wildcard in the base type %s",
10347 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10348 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010349 return (1);
10350 }
10351 /* 4.3 Unless the {base type definition} is the ·ur-type
10352 * definition·, the complex type definition's {attribute
10353 * wildcard}'s {process contents} must be identical to or
10354 * stronger than the {base type definition}'s {attribute
10355 * wildcard}'s {process contents}, where strict is stronger
10356 * than lax is stronger than skip.
10357 */
10358 if ((type->baseType != anyType) &&
10359 (type->attributeWildcard->processContents <
10360 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010361 xmlSchemaPCustomErr(ctxt,
10362 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10363 NULL, type, NULL,
10364 "The 'process contents' of the attribute wildcard is weaker than "
10365 "the one in the base type %s",
10366 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10367 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010368 return (1);
10369 }
10370 }
10371 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10372 /*
10373 * Derivation Valid (Extension)
10374 * At this point the type and the base have both, either
10375 * no wildcard or a wildcard.
10376 */
10377 if ((baseType->attributeWildcard != NULL) &&
10378 (baseType->attributeWildcard != type->attributeWildcard)) {
10379 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010380 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010381 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010382 xmlSchemaPCustomErr(ctxt,
10383 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10384 NULL, type, NULL,
10385 "The attribute wildcard is not a valid "
10386 "superset of the one in the base type %s",
10387 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10388 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010389 return (1);
10390 }
10391 }
10392 }
10393
Daniel Veillard3646d642004-06-02 19:19:14 +000010394 /*
10395 * Gather attribute uses defined by this type.
10396 */
10397 if (attrs != NULL) {
10398 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10399 &uses, &lastUse) == -1) {
10400 return (-1);
10401 }
10402 }
10403 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10404 * "Two distinct attribute declarations in the {attribute uses} must
10405 * not have identical {name}s and {target namespace}s."
10406 *
10407 * For "extension" this is done further down.
10408 */
10409 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10410 cur = uses;
10411 while (cur != NULL) {
10412 tmp = cur->next;
10413 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010414 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10415 xmlSchemaGetAttrName(tmp->attr))) &&
10416 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10417 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10418
10419 xmlSchemaPAttrUseErr(ctxt,
10420 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10421 NULL, type, NULL, cur->attr,
10422 "Duplicate attribute use %s specified",
10423 xmlSchemaFormatNsUriLocal(&str,
10424 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10425 xmlSchemaGetAttrName(tmp->attr))
10426 );
10427 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010428 break;
10429 }
10430 tmp = tmp->next;
10431 }
10432 cur = cur->next;
10433 }
10434 }
10435 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10436 /*
10437 * Derive by restriction.
10438 */
10439 if (baseIsAnyType) {
10440 type->attributeUses = uses;
10441 } else {
10442 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010443 const xmlChar *bEffValue;
10444 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010445
10446 cur = uses;
10447 while (cur != NULL) {
10448 found = 0;
10449 base = type->attributeUses;
10450 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010451 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10452 xmlSchemaGetAttrName(base->attr)) &&
10453 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10454 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010455
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010456 found = 1;
10457
Daniel Veillard3646d642004-06-02 19:19:14 +000010458 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10459 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10460 /*
10461 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010462 */
10463 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010464 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010465 NULL, type, NULL, cur->attr,
10466 "The 'optional' use is inconsistent with a matching "
10467 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010468 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10469 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10470 /*
10471 * derivation-ok-restriction 3
10472 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010473 xmlSchemaPCustomErr(ctxt,
10474 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10475 NULL, type, NULL,
10476 "A matching attribute use for the 'required' "
10477 "attribute use %s of the base type is missing",
10478 xmlSchemaFormatNsUriLocal(&str,
10479 xmlSchemaGetAttrTargetNsURI(base->attr),
10480 xmlSchemaGetAttrName(base->attr)));
10481 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010482 } else {
10483 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010484 * 2.1.3 [Definition:] Let the effective value
10485 * constraint of an attribute use be its {value
10486 * constraint}, if present, otherwise its {attribute
10487 * declaration}'s {value constraint} .
10488 */
10489 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10490 &bEffValue, 0);
10491 /*
10492 * 2.1.3 ... one of the following must be true
10493 *
10494 * 2.1.3.1 B's ·effective value constraint· is
10495 * ·absent· or default.
10496 */
10497 if ((bEffValue != NULL) &&
10498 (effFixed == 1)) {
10499 const xmlChar *rEffValue = NULL;
10500
10501 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10502 &rEffValue, 0);
10503 /*
10504 * 2.1.3.2 R's ·effective value constraint· is
10505 * fixed with the same string as B's.
10506 */
10507 if ((effFixed == 0) ||
10508 (! xmlStrEqual(rEffValue, bEffValue))) {
10509 xmlSchemaPAttrUseErr(ctxt,
10510 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10511 NULL, type, NULL, cur->attr,
10512 "The effective value constraint of the "
10513 "attribute use is inconsistent with "
10514 "its correspondent of the base type",
10515 NULL);
10516 }
10517 }
10518 /*
10519 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10520 */
10521 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010522 * Override the attribute use.
10523 */
10524 base->attr = cur->attr;
10525 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010526
Daniel Veillard3646d642004-06-02 19:19:14 +000010527 break;
10528 }
10529 base = base->next;
10530 }
10531
10532 if (!found) {
10533 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10534 /*
10535 * derivation-ok-restriction 2.2
10536 */
10537 if ((type->attributeWildcard != NULL) &&
10538 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10539 cur->attr->targetNamespace))
10540 found = 1;
10541
10542 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010543 xmlSchemaPAttrUseErr(ctxt,
10544 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10545 NULL, type, NULL, cur->attr,
10546 "Neither a matching attribute use, "
10547 "nor a matching wildcard in the base type does exist",
10548 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010549 } else {
10550 /*
10551 * Add the attribute use.
10552 *
10553 * Note that this may lead to funny derivation error reports, if
10554 * multiple equal attribute uses exist; but this is not
10555 * allowed anyway, and it will be reported beforehand.
10556 */
10557 tmp = cur;
10558 if (prev != NULL)
10559 prev->next = cur->next;
10560 else
10561 uses = cur->next;
10562 cur = cur->next;
10563 if (type->attributeUses == NULL) {
10564 type->attributeUses = tmp;
10565 } else
10566 lastBaseUse->next = tmp;
10567 lastBaseUse = tmp;
10568
10569 continue;
10570 }
10571 }
10572 }
10573 prev = cur;
10574 cur = cur->next;
10575 }
10576 if (uses != NULL)
10577 xmlSchemaFreeAttributeUseList(uses);
10578 }
10579 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10580 /*
10581 * The spec allows only appending, and not other kinds of extensions.
10582 *
10583 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10584 */
10585 if (uses != NULL) {
10586 if (type->attributeUses == NULL) {
10587 type->attributeUses = uses;
10588 } else
10589 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010590 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010591 } else {
10592 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010593 * Derive implicitely from the ur-type.
10594 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010595 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010596 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010597 /*
10598 * 3.4.6 -> Complex Type Definition Properties Correct
10599 */
10600 if (type->attributeUses != NULL) {
10601 cur = type->attributeUses;
10602 prev = NULL;
10603 while (cur != NULL) {
10604 /*
10605 * 4. Two distinct attribute declarations in the {attribute uses} must
10606 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010607 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010608 * Note that this was already done for "restriction" and types derived from
10609 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010610 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010611 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10612 tmp = cur->next;
10613 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010614 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10615 xmlSchemaGetAttrName(tmp->attr))) &&
10616 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10617 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010618
Daniel Veillardc0826a72004-08-10 14:17:33 +000010619 xmlSchemaPAttrUseErr(ctxt,
10620 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10621 NULL, type, NULL, tmp->attr,
10622 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010623 break;
10624 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010625 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010626 }
10627 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010628 /*
10629 * 5. Two distinct attribute declarations in the {attribute uses} must
10630 * not have {type definition}s which are or are derived from ID.
10631 */
10632 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010633 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010634 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010635 xmlSchemaPAttrUseErr(ctxt,
10636 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10637 NULL, type, NULL, cur->attr,
10638 "There must not exist more than one attribute use, "
10639 "declared of type 'ID' or derived from it",
10640 NULL);
10641 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010642 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010643 id = cur;
10644 }
10645 /*
10646 * Remove "prohibited" attribute uses. The reason this is done at this late
10647 * stage is to be able to catch dublicate attribute uses. So we had to keep
10648 * prohibited uses in the list as well.
10649 */
10650 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10651 tmp = cur;
10652 if (prev == NULL)
10653 type->attributeUses = cur->next;
10654 else
10655 prev->next = cur->next;
10656 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010657 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010658 } else {
10659 prev = cur;
10660 cur = cur->next;
10661 }
10662 }
10663 }
10664 /*
10665 * TODO: This check should be removed if we are 100% sure of
10666 * the base type attribute uses already being built.
10667 */
10668 if ((baseType != NULL) && (!baseIsAnyType) &&
10669 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10670 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010671 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010672 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010673 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010674 baseType->name, NULL);
10675 }
10676 return (0);
10677}
10678
10679/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010680 * xmlSchemaTypeFinalContains:
10681 * @schema: the schema
10682 * @type: the type definition
10683 * @final: the final
10684 *
10685 * Evaluates if a type definition contains the given "final".
10686 * This does take "finalDefault" into account as well.
10687 *
10688 * Returns 1 if the type does containt the given "final",
10689 * 0 otherwise.
10690 */
10691static int
10692xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10693{
10694 int tfinal = final, tflags = type->flags;
10695
10696 if (type == NULL)
10697 return (0);
10698 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10699 switch (final) {
10700 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10701 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10702 break;
10703 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10704 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10705 break;
10706 case XML_SCHEMAS_TYPE_FINAL_LIST:
10707 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10708 break;
10709 case XML_SCHEMAS_TYPE_FINAL_UNION:
10710 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10711 break;
10712 }
10713 tflags = schema->flags;
10714 }
10715 if (tflags & tfinal)
10716 return (1);
10717 else
10718 return (0);
10719
10720}
10721
10722/**
10723 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10724 * @type: the Union Simple Type
10725 *
10726 * Returns a list of member types of @type if existing,
10727 * returns NULL otherwise.
10728 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010729static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010730xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10731{
10732 while (type != NULL) {
10733 if (type->memberTypes != NULL)
10734 return (type->memberTypes);
10735 else
10736 type = type->baseType;
10737 }
10738 return (NULL);
10739}
10740
10741/**
10742 * xmlSchemaGetListSimpleTypeItemType:
10743 * @type: the simple type definition
10744 *
10745 * Returns the item type definition of the list simple type.
10746 */
10747static xmlSchemaTypePtr
10748xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10749{
10750 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10751 return (NULL);
10752 /*
10753 * Note: In libxml2, the built-in types do not reflect
10754 * the datatype hierarchy (yet?) - we have to treat them
10755 * in a special way.
10756 */
10757 if (type->type == XML_SCHEMA_TYPE_BASIC)
10758 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10759 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10760 /* 1 If the <list> alternative is chosen, then the type
10761 * definition ·resolved· to by the ·actual value· of the
10762 * itemType [attribute] of <list>, if present, otherwise
10763 * the type definition corresponding to the <simpleType>
10764 * among the [children] of <list>.
10765 */
10766 return (type->subtypes->subtypes);
10767 else {
10768 /* 2 If the <restriction> option is chosen, then the
10769 * {item type definition} of the {base type definition}.
10770 */
10771 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10772 }
10773}
10774
10775/**
10776 * xmlSchemaCheckCOSSTDerivedOK:
10777 * @type: the derived simple type definition
10778 * @baseType: the base type definition
10779 *
10780 * Checks wheter @type can be validly
10781 * derived from @baseType.
10782 *
10783 * Returns 0 on success, an positive error code otherwise.
10784 */
10785static int
10786xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10787 xmlSchemaTypePtr type,
10788 xmlSchemaTypePtr baseType,
10789 int subset)
10790{
10791 /*
10792 * Schema Component Constraint: Type Derivation OK (Simple)
10793 *
10794 *
10795 * 1 They are the same type definition.
10796 * TODO: The identy check might have to be more complex than this.
10797 */
10798 if (type == baseType)
10799 return (0);
10800 /*
10801 * 2.1 restriction is not in the subset, or in the {final}
10802 * of its own {base type definition};
10803 */
10804 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10805 (xmlSchemaTypeFinalContains(schema,
10806 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10807 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10808 }
10809 /* 2.2 */
10810 if (type->baseType == baseType) {
10811 /*
10812 * 2.2.1 D's ·base type definition· is B.
10813 */
10814 return (0);
10815 }
10816 /*
10817 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10818 * and is validly derived from B given the subset, as defined by this
10819 * constraint.
10820 */
10821 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10822 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10823 return (0);
10824 }
10825 /*
10826 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10827 * definition·.
10828 */
10829 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10830 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10831 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10832 return (0);
10833 }
10834 /*
10835 * 2.2.4 B's {variety} is union and D is validly derived from a type
10836 * definition in B's {member type definitions} given the subset, as
10837 * defined by this constraint.
10838 *
10839 * NOTE: This seems not to involve built-in types, since there is no
10840 * built-in Union Simple Type.
10841 */
10842 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10843 xmlSchemaTypeLinkPtr cur;
10844
10845 cur = baseType->memberTypes;
10846 while (cur != NULL) {
10847 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10848 cur->type, subset) == 0)
10849 return (0);
10850 cur = cur->next;
10851 }
10852 }
10853
10854 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10855}
10856
10857
10858/**
10859 * xmlSchemaCheckSTPropsCorrect:
10860 * @ctxt: the schema parser context
10861 * @type: the simple type definition
10862 *
10863 * Checks st-props-correct.
10864 *
10865 * Returns 0 if the properties are correct,
10866 * if not, a positive error code and -1 on internal
10867 * errors.
10868 */
10869static int
10870xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10871 xmlSchemaTypePtr type)
10872{
10873 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10874 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010875 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010876
Daniel Veillardc0826a72004-08-10 14:17:33 +000010877 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010878 /*
10879 * Schema Component Constraint: Simple Type Definition Properties Correct
10880 *
10881 * NOTE: This is somehow redundant, since we actually built a simple type
10882 * to have all the needed information; this acts as an self test.
10883 */
10884 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10885 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10886 /*
10887 * TODO: 1 The values of the properties of a simple type definition must be as
10888 * described in the property tableau in Datatype definition, modulo the
10889 * impact of Missing Sub-components (§5.3).
10890 */
10891 /* Base type: If the datatype has been ·derived· by ·restriction·
10892 * then the Simple Type Definition component from which it is ·derived·,
10893 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10894 */
10895 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010896 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010897 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010898 NULL, type, NULL,
10899 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010900 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10901 }
10902 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10903 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10904 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010905 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010906 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010907 NULL, type, NULL,
10908 "The base type %s is not a simple type",
10909 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10910 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010911 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10912 }
10913 if ((baseType != anySimpleType) &&
10914 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010915 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010916 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010917 NULL, type, NULL,
10918 "A type, derived by list or union, must have"
10919 "the simple ur-type definition as base type, not %s",
10920 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10921 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010922 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10923 }
10924 /*
10925 * Variety: One of {atomic, list, union}.
10926 */
10927 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10928 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10929 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010930 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010931 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010932 NULL, type, NULL,
10933 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010934 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10935 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010936 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010937
10938 /*
10939 * 2 All simple type definitions must be derived ultimately from the ·simple
10940 * ur-type definition (so· circular definitions are disallowed). That is, it
10941 * must be possible to reach a built-in primitive datatype or the ·simple
10942 * ur-type definition· by repeatedly following the {base type definition}.
10943 */
10944 baseType = type->baseType;
10945 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10946 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10947 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10948 if (baseType == anySimpleType)
10949 break;
10950 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010951 xmlSchemaPCustomErr(ctxt,
10952 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10953 NULL, type, NULL,
10954 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010955 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10956 }
10957 baseType = baseType->baseType;
10958 }
10959 /*
10960 * 3 The {final} of the {base type definition} must not contain restriction.
10961 */
10962 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10963 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010964 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010965 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010966 NULL, type, NULL,
10967 "The 'final' of its base type %s must not contain "
10968 "'restriction'",
10969 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10970 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010971 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10972 }
10973 return (0);
10974}
10975
10976/**
10977 * xmlSchemaCheckDerivationValidSimpleRestriction:
10978 * @ctxt: the schema parser context
10979 * @type: the simple type definition
10980 *
10981 * Checks if the given @type (simpleType) is derived
10982 * validly by restriction.
10983 *
10984 * Returns -1 on internal errors, 0 if the type is validly derived,
10985 * a positive error code otherwise.
10986 */
10987static int
10988xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010989 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010990{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010991 xmlChar *str = NULL;
10992
10993 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010994
10995 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10996 xmlSchemaPErr(ctxt, type->node,
10997 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010998 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10999 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011000 type->name, NULL);
11001 return (-1);
11002 }
11003
11004 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11005 xmlSchemaTypePtr primitive;
11006 /*
11007 * 1.1 The {base type definition} must be an atomic simple
11008 * type definition or a built-in primitive datatype.
11009 */
11010 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011011 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011012 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011013 NULL, type, NULL,
11014 "The base type %s is not an atomic simple type",
11015 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11016 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011017 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11018 }
11019 /* 1.2 The {final} of the {base type definition} must not contain
11020 * restriction.
11021 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011022 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011023 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11024 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011025 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011026 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011027 NULL, type, NULL,
11028 "The final of its base type %s must not contain 'restriction'",
11029 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11030 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011031 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11032 }
11033
11034 /*
11035 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11036 * type definition}, as specified in the appropriate subsection of 3.2
11037 * Primitive datatypes.
11038 */
11039 if (type->facets != NULL) {
11040 xmlSchemaFacetPtr facet;
11041 int ok = 1;
11042
11043 primitive = xmlSchemaGetPrimitiveType(type);
11044 if (primitive == NULL) {
11045 xmlSchemaPErr(ctxt, type->node,
11046 XML_ERR_INTERNAL_ERROR,
11047 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011048 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011049 type->name, NULL);
11050 return (-1);
11051 }
11052 facet = type->facets;
11053 do {
11054 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011055 ok = 0;
11056 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011057 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011058 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011059 }
11060 facet = facet->next;
11061 } while (facet != NULL);
11062 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011063 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011064 }
11065 /*
11066 * TODO: 1.3.2 (facet derivation)
11067 */
11068 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11069 xmlSchemaTypePtr itemType = NULL;
11070
11071 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11072 if (itemType == NULL) {
11073 xmlSchemaPErr(ctxt, type->node,
11074 XML_ERR_INTERNAL_ERROR,
11075 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011076 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011077 type->name, NULL);
11078 return (-1);
11079 }
11080 /*
11081 * 2.1 The {item type definition} must have a {variety} of atomic or
11082 * union (in which case all the {member type definitions}
11083 * must be atomic).
11084 */
11085 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11086 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011087 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011088 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011089 NULL, type, NULL,
11090 "The item type %s must have a variety of atomic or union",
11091 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11092 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011093 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11094 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11095 xmlSchemaTypeLinkPtr member;
11096
11097 member = itemType->memberTypes;
11098 while (member != NULL) {
11099 if ((member->type->flags &
11100 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011102 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 NULL, type, NULL,
11104 "The item type is a union type, but the "
11105 "member type %s of this item type is not atomic",
11106 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11107 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011108 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11109 }
11110 member = member->next;
11111 }
11112 }
11113
11114 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11115 xmlSchemaFacetPtr facet;
11116 /*
11117 * This is the case if we have: <simpleType><list ..
11118 */
11119 /*
11120 * 2.3.1
11121 * 2.3.1.1 The {final} of the {item type definition} must not
11122 * contain list.
11123 */
11124 if (xmlSchemaTypeFinalContains(ctxt->schema,
11125 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011126 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011127 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 NULL, type, NULL,
11129 "The final of its item type %s must not contain 'list'",
11130 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11131 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011132 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11133 }
11134 /*
11135 * 2.3.1.2 The {facets} must only contain the whiteSpace
11136 * facet component.
11137 */
11138 if (type->facets != NULL) {
11139 facet = type->facets;
11140 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011141 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11142 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011143 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011144 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011145 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11146 }
11147 facet = facet->next;
11148 } while (facet != NULL);
11149 }
11150 /*
11151 * TODO: Datatypes states:
11152 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11153 * whose ·lexical space· allows space (such as string or anyURI)or
11154 * a ·union· datatype any of whose {member type definitions}'s
11155 * ·lexical space· allows space.
11156 */
11157 } else {
11158 /*
11159 * This is the case if we have: <simpleType><restriction ...
11160 */
11161 /*
11162 * 2.3.2
11163 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11164 */
11165 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011166 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011167 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011168 NULL, type, NULL,
11169 "The base type %s must be a list type",
11170 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11171 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011172 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11173 }
11174 /*
11175 * 2.3.2.2 The {final} of the {base type definition} must not
11176 * contain restriction.
11177 */
11178 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11179 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011180 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011181 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011182 NULL, type, NULL,
11183 "The final of the base type %s must not contain 'restriction'",
11184 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11185 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011186 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11187 }
11188 /*
11189 * 2.3.2.3 The {item type definition} must be validly derived
11190 * from the {base type definition}'s {item type definition} given
11191 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11192 */
11193 {
11194 xmlSchemaTypePtr baseItemType;
11195
11196 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11197 if (baseItemType == NULL) {
11198 xmlSchemaPErr(ctxt, type->node,
11199 XML_ERR_INTERNAL_ERROR,
11200 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011201 "List simple type '%s': Failed to "
11202 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011203 type->name, type->baseType->name);
11204 return (-1);
11205 }
11206 if ((itemType != baseItemType) &&
11207 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11208 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011209 xmlChar *strBIT = NULL, *strBT = NULL;
11210 xmlSchemaPCustomErrExt(ctxt,
11211 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11212 NULL, type, NULL,
11213 "The item type %s is not validly derived from the "
11214 "item type %s of the base type %s",
11215 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11216 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11217 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11218
11219 FREE_AND_NULL(str)
11220 FREE_AND_NULL(strBIT)
11221 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011222 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11223 }
11224 }
11225
11226 if (type->facets != NULL) {
11227 xmlSchemaFacetPtr facet;
11228 int ok = 1;
11229 /*
11230 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11231 * and enumeration facet components are allowed among the {facets}.
11232 */
11233 facet = type->facets;
11234 do {
11235 switch (facet->type) {
11236 case XML_SCHEMA_FACET_LENGTH:
11237 case XML_SCHEMA_FACET_MINLENGTH:
11238 case XML_SCHEMA_FACET_MAXLENGTH:
11239 case XML_SCHEMA_FACET_WHITESPACE:
11240 /*
11241 * TODO: 2.5.1.2 List datatypes
11242 * The value of ·whiteSpace· is fixed to the value collapse.
11243 */
11244 case XML_SCHEMA_FACET_PATTERN:
11245 case XML_SCHEMA_FACET_ENUMERATION:
11246 break;
11247 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011248 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011249 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011250 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011251 /*
11252 * We could return, but it's nicer to report all
11253 * invalid facets.
11254 */
11255 ok = 0;
11256 }
11257 }
11258 facet = facet->next;
11259 } while (facet != NULL);
11260 if (ok == 0)
11261 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11262 /*
11263 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11264 * is a facet of the same kind in the {facets} of the {base type
11265 * definition} (call this BF),then the DF's {value} must be a valid
11266 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11267 */
11268 }
11269
11270
11271 }
11272 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11273 /*
11274 * 3.1 The {member type definitions} must all have {variety} of
11275 * atomic or list.
11276 */
11277 xmlSchemaTypeLinkPtr member;
11278
11279 member = type->memberTypes;
11280 while (member != NULL) {
11281 if (((member->type->flags &
11282 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11283 ((member->type->flags &
11284 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011285 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011286 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011287 NULL, type, NULL,
11288 "The member type %s is neither an atomic, nor a list type",
11289 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11290 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011291 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11292 }
11293 member = member->next;
11294 }
11295 /*
11296 * 3.3.1 If the {base type definition} is the ·simple ur-type
11297 * definition·
11298 */
11299 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11300 /*
11301 * 3.3.1.1 All of the {member type definitions} must have a
11302 * {final} which does not contain union.
11303 */
11304 member = type->memberTypes;
11305 while (member != NULL) {
11306 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11307 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011308 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011309 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011310 NULL, type, NULL,
11311 "The final of member type %s contains 'union'",
11312 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11313 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011314 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11315 }
11316 member = member->next;
11317 }
11318 /*
11319 * 3.3.1.2 The {facets} must be empty.
11320 */
11321 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011322 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011323 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011324 NULL, type, NULL,
11325 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011326 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11327 }
11328 } else {
11329 /*
11330 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11331 */
11332 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011333 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011334 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011335 NULL, type, NULL,
11336 "The base type %s is not a union type",
11337 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11338 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011339 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11340 }
11341 /*
11342 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11343 */
11344 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11345 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011346 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011347 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011348 NULL, type, NULL,
11349 "The final of its base type %s must not contain 'restriction'",
11350 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11351 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011352 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11353 }
11354 /*
11355 * 3.3.2.3 The {member type definitions}, in order, must be validly
11356 * derived from the corresponding type definitions in the {base
11357 * type definition}'s {member type definitions} given the empty set,
11358 * as defined in Type Derivation OK (Simple) (§3.14.6).
11359 */
11360 {
11361 xmlSchemaTypeLinkPtr baseMember;
11362
11363 /*
11364 * OPTIMIZE: if the type is restricting, it has no local defined
11365 * member types and inherits the member types of the base type;
11366 * thus a check for equality can be skipped.
11367 */
11368 /*
11369 * TODO: Even worse: I cannot see a scenario where a restricting
11370 * union simple type can have other member types as the member
11371 * types of it's base type. This check seems not necessary with
11372 * respect to the derivation process in libxml2.
11373 */
11374 if (type->memberTypes != NULL) {
11375 member = type->memberTypes;
11376 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11377 if ((member == NULL) && (baseMember != NULL)) {
11378 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011379 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011380 "Internal error: "
11381 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011382 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011383 "of member types in the base type\n",
11384 type->name, NULL);
11385 }
11386 while (member != NULL) {
11387 if (baseMember == NULL) {
11388 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011389 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011390 "Internal error: "
11391 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011392 "(3.3.2.3), union simple type '%s', unequal number "
11393 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011394 type->name, NULL);
11395 }
11396 if ((member->type != baseMember->type) &&
11397 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11398 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011399 xmlChar *strBMT = NULL, *strBT = NULL;
11400
11401 xmlSchemaPCustomErrExt(ctxt,
11402 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11403 NULL, type, NULL,
11404 "The member type %s is not validly derived from its "
11405 "corresponding member type %s of the base type %s",
11406 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11407 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11408 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11409 FREE_AND_NULL(str)
11410 FREE_AND_NULL(strBMT)
11411 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011412 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11413 }
11414 member = member->next;
11415 baseMember = baseMember->next;
11416 }
11417 }
11418 }
11419 /*
11420 * 3.3.2.4 Only pattern and enumeration facet components are
11421 * allowed among the {facets}.
11422 */
11423 if (type->facets != NULL) {
11424 xmlSchemaFacetPtr facet;
11425 int ok = 1;
11426
11427 facet = type->facets;
11428 do {
11429 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11430 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011431 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11432 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11433 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011434 ok = 0;
11435 }
11436 facet = facet->next;
11437 } while (facet != NULL);
11438 if (ok == 0)
11439 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11440
11441 }
11442 /*
11443 * TODO: 3.3.2.5 (facet derivation)
11444 */
11445 }
11446 }
11447
11448 return (0);
11449}
11450
11451/**
11452 * xmlSchemaCheckSRCSimpleType:
11453 * @ctxt: the schema parser context
11454 * @type: the simple type definition
11455 *
11456 * Checks crc-simple-type constraints.
11457 *
11458 * Returns 0 if the constraints are satisfied,
11459 * if not a positive error code and -1 on internal
11460 * errors.
11461 */
11462static int
11463xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11464 xmlSchemaTypePtr type)
11465{
11466 /*
11467 * NOTE: src-simple-type 2-4 are redundant, since the checks
11468 * were are done for the corresponding <restriction>, <list> and <union>
11469 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11470 * Maby this can be skipped in the future, if we get sure it's not needed.
11471 */
11472 if (type->subtypes == NULL) {
11473 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011474 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011475 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011476 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011477 type->name, NULL);
11478 return (-1);
11479 }
11480 /*
11481 * src-simple-type.1 The corresponding simple type definition, if any,
11482 * must satisfy the conditions set out in Constraints on Simple Type
11483 * Definition Schema Components (§3.14.6).
11484 */
11485 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11486 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11487 /*
11488 * TODO: Removed this, since it got annoying to get an
11489 * extra error report, if anything failed until now.
11490 * Enable this if needed.
11491 */
11492 /*
11493 xmlSchemaPErr(ctxt, type->node,
11494 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011495 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011496 "on simple type definitions.\n",
11497 type->name, NULL);
11498 */
11499 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11500 }
11501
11502 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11503 /*
11504 * src-simple-type.2 If the <restriction> alternative is chosen,
11505 * either it must have a base [attribute] or a <simpleType> among its
11506 * [children], but not both.
11507 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011508 /*
11509 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11510 * NOTE: This was removed, since this will be already handled
11511 * in the parse function for <restriction>.
11512 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011513 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11514 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11515 * an itemType [attribute] or a <simpleType> among its [children],
11516 * but not both.
11517 * NOTE: baseType is set to the local simple type definiton,
11518 * if existent, at parse time. This is a hack and not nice.
11519 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011520 /*
11521 * TODO: Remove this, and add the check to the parse function of <list>.
11522 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011523 if (((type->subtypes->base == NULL) &&
11524 (type->baseType == NULL)) ||
11525 ((type->subtypes->base != NULL) &&
11526 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011527 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011528 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011529 NULL, type, NULL,
11530 "Either the attribute 'itemType' or the <simpleType> child "
11531 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011532 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11533 }
11534
11535
11536 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11537 xmlSchemaTypeLinkPtr member;
11538 xmlSchemaTypePtr ancestor, anySimpleType;
11539
11540 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11541
11542 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11543 * the <union> alternative is chosen, there must not be any entries
11544 * in the memberTypes [attribute] at any depth which resolve to the
11545 * component corresponding to the <simpleType>.
11546 */
11547 member = type->memberTypes;
11548 while (member != NULL) {
11549 ancestor = member->type;
11550 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11551 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11552 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11553 if (ancestor == anySimpleType)
11554 break;
11555 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011556 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011557 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011558 NULL, type, NULL,
11559 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011560 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11561 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11562 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011563 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011564 * type as item type, which in turn has a list ST as member
11565 * type, we will assume this here as well, since this check
11566 * was not yet performed.
11567 */
11568
11569 }
11570 ancestor = ancestor->baseType;
11571 }
11572 member = member->next;
11573 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011574 }
11575
11576 return (0);
11577}
11578
William M. Brack2f2a6632004-08-20 23:09:47 +000011579#if 0 /* Not yet used code for CT schema validation */
11580static int
11581xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11582 const xmlChar * value,
11583 xmlSchemaTypePtr type,
11584 int fireErrors)
11585{
11586 int ret;
11587 /*
11588 * 3.14.4 Simple Type Definition Validation Rules
11589 * Validation Rule: String Valid
11590 */
11591 /*
11592 * 1 It is schema-valid with respect to that definition as defined
11593 * by Datatype Valid in [XML Schemas: Datatypes].
11594 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011595 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11596 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011597 return (ret);
11598 /*
11599 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11600 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11601 * the string must be a ·declared entity name·.
11602 */
11603 /*
11604 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11605 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11606 * then every whitespace-delimited substring of the string must be a ·declared
11607 * entity name·.
11608 */
11609 /*
11610 * 2.3 otherwise no further condition applies.
11611 */
11612
11613 return (0);
11614}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011615#endif
11616
William M. Brack2f2a6632004-08-20 23:09:47 +000011617
11618static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011619xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11620{
11621 if (vctxt->pctxt == NULL) {
11622 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11623 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11624 if (vctxt->pctxt == NULL) {
11625 xmlSchemaVErr(vctxt, NULL,
11626 XML_SCHEMAV_INTERNAL,
11627 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11628 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011629 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011630 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011631 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011632 /* TODO: Pass user data. */
11633 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11634 }
11635 return (0);
11636}
11637
11638static int
11639xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11640{
11641 if (ctxt->vctxt == NULL) {
11642 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11643 if (ctxt->vctxt == NULL) {
11644 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011645 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011646 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11647 "failed to create a temp. validation context.\n",
11648 NULL, NULL);
11649 return (-1);
11650 }
11651 /* TODO: Pass user data. */
11652 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11653 }
11654 return (0);
11655}
11656
11657/**
11658 * xmlSchemaCheckCOSValidDefault:
11659 * @ctxt: the schema parser context
11660 * @type: the simple type definition
11661 * @value: the default value
11662 * @node: an optional node (the holder of the value)
11663 *
11664 * Checks the "cos-valid-default" constraints.
11665 *
11666 * Returns 0 if the constraints are satisfied,
11667 * if not, a positive error code and -1 on internal
11668 * errors.
11669 */
11670static int
11671xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11672 xmlSchemaValidCtxtPtr vctxt,
11673 xmlSchemaTypePtr type,
11674 const xmlChar *value,
11675 xmlNodePtr node)
11676{
11677 int ret = 0;
11678
11679 /*
11680 * cos-valid-default:
11681 * Schema Component Constraint: Element Default Valid (Immediate)
11682 * For a string to be a valid default with respect to a type
11683 * definition the appropriate case among the following must be true:
11684 */
11685 /*
11686 * NOTE: This has to work without a given node (the holder of the
11687 * value), since it should work on the component, i.e. an underlying
11688 * DOM must not be mandatory.
11689 */
11690 if ((pctxt == NULL) || (vctxt == NULL)) {
11691 xmlSchemaPErr(pctxt, node,
11692 XML_SCHEMAP_INTERNAL,
11693 "Internal error: xmlSchemaCheckCOSValidDefault, "
11694 "bad arguments: the parser and/or validation context is "
11695 "missing.\n",
11696 NULL, NULL);
11697 return (-1);
11698 }
11699 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011700 /*
11701 * Complex type.
11702 *
11703 * 2.1 its {content type} must be a simple type definition or mixed.
11704 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011705 /*
11706 * TODO: Adjust this when the content type will be computed
11707 * correctly.
11708 */
11709 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11710 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11711 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11712 xmlSchemaPSimpleTypeErr(pctxt,
11713 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11714 NULL, NULL, node,
11715 type, NULL, NULL,
11716 "If the type of a constraint value is complex, its content "
11717 "type must be mixed or a simple type",
11718 NULL, NULL);
11719 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11720 }
11721 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011722 /*
11723 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11724 * particle must be ·emptiable· as defined by Particle Emptiable
11725 * (§3.9.6).
11726 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011727
William M. Brack2f2a6632004-08-20 23:09:47 +000011728 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011729 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011730 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011731 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011732 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011733 }
11734 /*
11735 * 1 If the type definition is a simple type definition, then the string
11736 * must be ·valid· with respect to that definition as defined by String
11737 * Valid (§3.14.4).
11738 *
11739 * AND
11740 *
11741 * 2.2.1 If the {content type} is a simple type definition, then the
11742 * string must be ·valid· with respect to that simple type definition
11743 * as defined by String Valid (§3.14.4).
11744 */
11745 vctxt->node = node;
11746 vctxt->cur = NULL;
11747 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11748 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11749 if (ret < 0) {
11750 xmlSchemaPErr(pctxt, node,
11751 /* NOTNICE: error code: This function will be used during
11752 * schema construction and xsi:type validation.
11753 */
11754 XML_SCHEMAP_INTERNAL,
11755 "Internal error: xmlSchemaCheckCOSValidDefault, "
11756 "while validating a value constaint value.\n",
11757 NULL, NULL);
11758
11759 }
11760 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011761}
11762
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011763#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011764/**
11765 * xmlSchemaGetSTContentOfCT:
11766 * @ctxt: the schema parser context
11767 * @type: the complex type definition
11768 *
11769 *
11770 * Returns the corresponding simple type for the content of
11771 * the complex type.
11772 */
11773static xmlSchemaTypePtr
11774xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11775 xmlSchemaTypePtr type)
11776{
11777 xmlSchemaTypePtr orig = type, anyType;
11778
11779 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11780 while ((type != NULL) && (type != anyType) &&
11781 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11782 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11783 return(type);
11784 type = type->baseType;
11785 }
11786 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011787 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011788 NULL, orig, NULL,
11789 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11790 "no simple type for the content of complex type '%s' could be "
11791 "computed", orig->name);
11792 return (NULL);
11793}
11794
11795
William M. Brack2f2a6632004-08-20 23:09:47 +000011796
William M. Brack2f2a6632004-08-20 23:09:47 +000011797
11798/**
11799 * xmlSchemaCheckCOSCTExtends:
11800 * @ctxt: the schema parser context
11801 * @type: the complex type definition
11802 *
11803 * Schema Component Constraint: Derivation Valid (Extension)
11804 *
11805 * Returns 0 if the constraints are satisfied, a positive
11806 * error code if not and -1 if an internal error occured.
11807 */
11808static int
11809xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11810 xmlSchemaTypePtr type)
11811{
11812 xmlSchemaTypePtr base;
11813 /*
11814 * 1 If the {base type definition} is a complex type definition,
11815 * then all of the following must be true:
11816 */
11817 base = type->baseType;
11818 if (base == NULL) {
11819 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011820 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011821 NULL, type, NULL,
11822 "Internal error: xmlSchemaCheckCOSCTExtends, "
11823 "the complex type '%s' has no base type", type->name);
11824 return (-1);
11825 }
11826 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11827 /*
11828 * 1.1 The {final} of the {base type definition} must not
11829 * contain extension.
11830 */
11831 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11832 xmlSchemaPCustomErr(ctxt,
11833 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11834 NULL, type, NULL,
11835 "The 'final' of the base type definition "
11836 "contains extension", NULL);
11837 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11838 }
11839 /*
11840 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11841 * of the complex type definition itself, that is, for every attribute
11842 * use in the {attribute uses} of the {base type definition}, there
11843 * must be an attribute use in the {attribute uses} of the complex
11844 * type definition itself whose {attribute declaration} has the same
11845 * {name}, {target namespace} and {type definition} as its attribute
11846 * declaration
11847 *
11848 * NOTE: This will be already satisfied by the way the attribute uses
11849 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11850 * is not needed.
11851 */
11852
11853 /*
11854 * 1.3 If it has an {attribute wildcard}, the complex type definition
11855 * must also have one, and the base type definition's {attribute
11856 * wildcard}'s {namespace constraint} must be a subset of the complex
11857 * type definition's {attribute wildcard}'s {namespace constraint},
11858 * as defined by Wildcard Subset (§3.10.6).
11859 *
11860 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11861 * this check is not needed.
11862 */
11863
11864 /*
11865 * 1.4 One of the following must be true:
11866 *
11867 * 1.4.1 The {content type} of the {base type definition} and the
11868 * {content type} of the complex type definition itself must be the same
11869 * simple type definition
11870 */
11871
11872
11873
11874 } else {
11875 /*
11876 * 2 If the {base type definition} is a simple type definition,
11877 * then all of the following must be true:
11878 */
11879 /*
11880 * 2.1 The {content type} must be the same simple type definition.
11881 */
11882 /*
11883 * 2.2 The {final} of the {base type definition} must not contain
11884 * extension
11885 */
11886 }
11887
11888}
11889
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011890static int
11891xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11892 xmlSchemaTypePtr type)
11893{
11894 xmlSchemaTypePtr base, content;
11895 int OK = 0;
11896
11897 /*
11898 * TODO: Adjust the error codes here, as I used
11899 * XML_SCHEMAP_SRC_CT_1 only yet.
11900 */
11901 /*
11902 * Schema Representation Constraint:
11903 * Complex Type Definition Representation OK
11904 */
11905 base = type->baseType;
11906 if (base == NULL) {
11907 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11908 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11909 type->name);
11910 return (-1);
11911 }
11912
11913 if (type->subtypes != NULL) {
11914 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11915 if IS_COMPLEX_TYPE(base) {
11916 /*
11917 * 1 If the <complexContent> alternative is chosen, the type definition
11918 * ·resolved· to by the ·actual value· of the base [attribute]
11919 * must be a complex type definition;
11920 */
11921 xmlSchemaPCustomErr(ctxt,
11922 XML_SCHEMAP_SRC_CT_1,
11923 NULL, type, NULL,
11924 "The base type is not a complex type", NULL);
11925 return (XML_SCHEMAP_SRC_CT_1);
11926 }
11927 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11928
11929 if IS_SIMPLE_TYPE(base) {
11930 if (type->flags &
11931 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11932 /*
11933 * 2.1.3 only if the <extension> alternative is also
11934 * chosen, a simple type definition.
11935 */
11936 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11937 xmlSchemaPCustomErr(ctxt,
11938 XML_SCHEMAP_SRC_CT_1,
11939 NULL, type, NULL,
11940 "A complex type (simple content) cannot restrict "
11941 "an other simple type",
11942 NULL);
11943 return (XML_SCHEMAP_SRC_CT_1);
11944 }
11945 OK = 1;
11946
11947 } else { /* if IS_SIMPLE_TYPE(base) */
11948 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11949 /*
11950 * 2.1.2 only if the <restriction> alternative is also
11951 * chosen, a complex type definition whose {content type}
11952 * is mixed and a particle emptyable.
11953 */
11954 /*
11955 * FIXME TODO: Check for *empiable particle* is missing.
11956 */
11957 if ((type->flags &
11958 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11959 xmlSchemaPCustomErr(ctxt,
11960 XML_SCHEMAP_SRC_CT_1,
11961 NULL, type, NULL,
11962 "A complex type (simple content) cannot "
11963 "extend an other complex type which has a "
11964 "content type of: 'mixed' and emptiable particle",
11965 NULL);
11966 return (XML_SCHEMAP_SRC_CT_1);
11967 }
11968 /*
11969 * NOTE: This will be fired as well, if the base type
11970 * is *'anyType'*.
11971 * NOTE: type->subtypes->subtypes will be the
11972 * <restriction> item.
11973 */
11974 if (type->subtypes->subtypes == NULL) {
11975 /* Yes, this is paranoid programming. */
11976 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11977 NULL, type, NULL,
11978 "Internal error: xmlSchemaCheckSRCCT, "
11979 "'%s', <simpleContent> has no <restriction>",
11980 type->name);
11981 return (-1);
11982 }
11983 /*
11984 * 2.2 If clause 2.1.2 above is satisfied, then there
11985 * must be a <simpleType> among the [children] of
11986 * <restriction>.
11987 */
11988 if (type->subtypes->subtypes->type !=
11989 XML_SCHEMA_TYPE_SIMPLE) {
11990 /* TODO: Change error code to ..._SRC_CT_2_2. */
11991 xmlSchemaPCustomErr(ctxt,
11992 XML_SCHEMAP_SRC_CT_1,
11993 NULL, type, NULL,
11994 "A <simpleType> is expected among the children "
11995 "of <restriction>", NULL);
11996 return (XML_SCHEMAP_SRC_CT_1);
11997 }
11998 OK = 1;
11999 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12000 /*
12001 * 2.1.1 a complex type definition whose {content type} is a
12002 * simple type definition;
12003 */
12004 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12005 xmlSchemaPCustomErr(ctxt,
12006 XML_SCHEMAP_SRC_CT_1,
12007 NULL, type, NULL,
12008 "A complex type (simple content) cannot "
12009 "be derived from the complex type '%s'",
12010 base->name);
12011 return (XML_SCHEMAP_SRC_CT_1);
12012 }
12013 content = base->contentTypeDef;
12014 if (content == NULL) {
12015 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12016 NULL, type, NULL,
12017 "Internal error: xmlSchemaCheckSRCCT, "
12018 "'%s', base type has no content type",
12019 type->name);
12020 return (-1);
12021 }
12022 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12023 xmlSchemaPCustomErr(ctxt,
12024 XML_SCHEMAP_SRC_CT_1,
12025 NULL, type, NULL,
12026 "A complex type (simple content) cannot "
12027 "be derived from the complex type '%s'",
12028 base->name);
12029 return (XML_SCHEMAP_SRC_CT_1);
12030 }
12031 }
12032 }
12033 }
12034 }
12035 /*
12036 * TODO: 3 The corresponding complex type definition component must
12037 * satisfy the conditions set out in Constraints on Complex Type
12038 * Definition Schema Components (§3.4.6);
12039 *
12040 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12041 * above for {attribute wildcard} is satisfied, the intensional
12042 * intersection must be expressible, as defined in Attribute Wildcard
12043 * Intersection (§3.10.6).
12044 */
12045
12046}
William M. Brack2f2a6632004-08-20 23:09:47 +000012047#endif
12048
Daniel Veillard01fa6152004-06-29 17:04:39 +000012049/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012050 * xmlSchemaGroupDefFixup:
12051 * @typeDecl: the schema model group definition
12052 * @ctxt: the schema parser context
12053 *
12054 * Fixes model group definitions.
12055 */
12056static void
12057xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12058 xmlSchemaParserCtxtPtr ctxt,
12059 const xmlChar * name ATTRIBUTE_UNUSED)
12060{
12061 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12062 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12063 xmlSchemaTypePtr groupDef;
12064 /*
12065 * Resolve the reference.
12066 */
12067 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12068 group->refNs);
12069 if (groupDef == NULL) {
12070 xmlSchemaPResCompAttrErr(ctxt,
12071 XML_SCHEMAP_SRC_RESOLVE,
12072 NULL, group, NULL,
12073 "ref", group->ref, group->refNs,
12074 XML_SCHEMA_TYPE_GROUP, NULL);
12075 return;
12076 }
12077 group->subtypes = groupDef;
12078 }
12079}
12080
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012081#if 0 /* Enable when the content type will be computed. */
12082static int
12083xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12084 xmlSchemaTypePtr type)
12085{
12086 xmlSchemaTypePtr base, res = NULL;
12087
12088 base = type->baseType;
12089 if (base == NULL) {
12090 xmlSchemaPCustomErr(ctxt,
12091 XML_SCHEMAP_INTERNAL,
12092 NULL, type, NULL,
12093 "Internal error: xmlSchemaGetContentType, "
12094 "the complex type '%s' has no base type", type->name);
12095 return (-1);
12096 }
12097 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12098 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12099 xmlSchemaTypePtr start;
12100 /*
12101 * Effective 'mixed'.
12102 */
12103 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12104 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12105 /*
12106 * Effective content.
12107 */
12108 if (IS_ANYTYPE(base))
12109 start = type;
12110 else
12111 start = type->subtypes;
12112
12113 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12114 xmlSchemaTypePtr baseContentItem;
12115
12116 /*
12117 * Complex type with simple content.
12118 */
12119 if IS_COMPLEX_TYPE(base) {
12120 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12121 /*
12122 * Summary: a complex type (simple content) can *restrict*
12123 * a complex type with the following content type:
12124 * 1. 'mixed' and an emptiable particle
12125 * 2. simple type
12126 */
12127 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12128 /*
12129 * 2 if the {content type} of the base type is mixed and a
12130 * particle which is ·emptiable·,
12131 * [...]
12132 * then starting from the simple type definition
12133 * corresponding to the <simpleType> among the [children]
12134 * of <restriction> (**which must be present**)
12135 *
12136 * FIXME TODO: Handle "emptiable particle".
12137 */
12138 res = type->subtypes->subtypes;
12139 if (res == NULL) {
12140 xmlSchemaPCustomErr(ctxt,
12141 XML_SCHEMAP_INTERNAL,
12142 NULL, type, NULL,
12143 "Internal error: xmlSchemaGetContentType, "
12144 "CT '%s' (restricting): <simpleContent> has no "
12145 "<restriction>",
12146 type->name);
12147 return (-1);
12148 }
12149
12150 res->subtypes;
12151 if (res == NULL) {
12152 xmlSchemaPCustomErr(ctxt,
12153 XML_SCHEMAP_INTERNAL,
12154 NULL, type, NULL,
12155 "Internal error: xmlSchemaGetContentType, "
12156 "CT '%s' (restricting): <restriction> has no "
12157 "mandatory <simpleType>",
12158 type->name);
12159 return (-1);
12160 }
12161 } else {
12162 baseContentItem = base->contentTypeDef;
12163 if (baseContentItem == NULL) {
12164 xmlSchemaPCustomErr(ctxt,
12165 XML_SCHEMAP_INTERNAL,
12166 NULL, type, NULL,
12167 "Internal error: xmlSchemaGetContentType, "
12168 "CT '%s' (restricting), the base type has no "
12169 "content type", type->name);
12170 return (-1);
12171 }
12172 if IS_SIMPLE_TYPE(baseContentItem) {
12173 /*
12174 * 1 If the base type is a complex type whose own
12175 * {content type} is a simple type and the <restriction>
12176 * alternative is chosen
12177 */
12178 /* type->subtypes->subtypes will be the restriction item.*/
12179 res = type->subtypes->subtypes;
12180 if (res == NULL) {
12181 xmlSchemaPCustomErr(ctxt,
12182 XML_SCHEMAP_INTERNAL,
12183 NULL, type, NULL,
12184 "Internal error: xmlSchemaGetContentType, "
12185 "CT '%s' (restricting): <simpleType> has no "
12186 "<restriction>", type->name);
12187 return (-1);
12188 }
12189 /*
12190 * 1.1 the simple type definition corresponding to the
12191 * <simpleType> among the [children] of <restriction>if
12192 * there is one;
12193 */
12194 res = res->subtypes;
12195 if (res == NULL) {
12196 /*
12197 * 1.2 otherwise the {content type}
12198 * of the base type .
12199 */
12200 res = baseContentItem;
12201 }
12202 }
12203 }
12204 /*
12205 * SPECIAL TODO: If *restricting* the spec wants us to
12206 * create an *additional* simple type which restricts the
12207 * located simple type; we won't do this yet, and look how
12208 * far we get with it.
12209 */
12210 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12211 /*
12212 * Summary: a complex type (simple content) can *extend*
12213 * only a complex base with a simple type as content.
12214 */
12215 /*
12216 * 3 If the type definition ·resolved· to by the ·actual
12217 * value· of the base [attribute] is a complex type
12218 * definition (whose own {content type} *must be* a simple
12219 * type definition, see below) and the *<extension>*
12220 * alternative is chosen, then the {content type} of that
12221 * complex type definition;
12222 */
12223 res = base->contentTypeDef;
12224 if (res == NULL) {
12225 xmlSchemaPCustomErr(ctxt,
12226 XML_SCHEMAP_INTERNAL,
12227 NULL, type, NULL,
12228 "Internal error: xmlSchemaGetContentType, "
12229 "CT '%s' (extending), the base type has no content "
12230 "type", type->name);
12231 return (-1);
12232 }
12233 if (! IS_SIMPLE_TYPE(res)) {
12234 xmlSchemaPCustomErr(ctxt,
12235 XML_SCHEMAP_INTERNAL,
12236 NULL, type, NULL,
12237 "Internal error: xmlSchemaGetContentType, "
12238 "CT '%s' (extending), the content type of the "
12239 "base is not a simple type", type->name);
12240 return (-1);
12241 }
12242 }
12243 } else /* if IS_COMPLEX_TYPE(base) */
12244 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12245 /*
12246 * 4 otherwise (the type definition ·resolved· to by the
12247 * ·actual value· of the base [attribute] is a simple type
12248 * definition and the <extension> alternative is chosen),
12249 * then that simple type definition.
12250 */
12251 res = base;
12252 }
12253 type->contentTypeDef = res;
12254 if (res == NULL) {
12255 xmlSchemaPCustomErr(ctxt,
12256 XML_SCHEMAP_INTERNAL,
12257 NULL, type, NULL,
12258 "Internal error: xmlSchemaGetContentType, "
12259 "'%s', the content type could not be determined",
12260 type->name);
12261 return (-1);
12262 }
12263
12264 }
12265
12266}
12267#endif
12268
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012269/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012270 * xmlSchemaTypeFixup:
12271 * @typeDecl: the schema type definition
12272 * @ctxt: the schema parser context
12273 *
12274 * Fixes the content model of the type.
12275 */
12276static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012277xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012278 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012279{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012280 xmlSchemaTypePtr ctxtType;
12281
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012282 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012283 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012284 /*
12285 * Do not allow the following types to be typefixed, prior to
12286 * the corresponding simple/complex types.
12287 */
12288 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012289 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012290 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12291 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12292 case XML_SCHEMA_TYPE_UNION:
12293 case XML_SCHEMA_TYPE_RESTRICTION:
12294 case XML_SCHEMA_TYPE_EXTENSION:
12295 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012296 default:
12297 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012298 }
12299 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012300 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012301 name = item->name;
12302 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12303 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012304 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012305 if (item->subtypes != NULL) {
12306 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012307 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012308 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012309 NULL);
12310 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012311 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012312 XML_SCHEMA_CONTENT_SIMPLE;
12313 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012314 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012315 break;
12316 }
12317 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012318 xmlSchemaTypePtr base = NULL;
12319
12320 ctxt->ctxtType->flags |=
12321 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012322 if (item->baseType != NULL)
12323 base = item->baseType;
12324 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012325 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012326 xmlSchemaGetType(ctxt->schema, item->base,
12327 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012328 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012329 xmlSchemaPResCompAttrErr(ctxt,
12330 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012331 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012332 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12333 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012334 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012335 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012336 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012337 xmlSchemaTypeFixup(base, ctxt, NULL);
12338 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012339 }
12340 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012341 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12342 /*
12343 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012344 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012345 /*
12346 * Content type.
12347 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012348 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012349 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012350 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12351 else if ((item->subtypes->subtypes == NULL) &&
12352 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012353 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012354 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012355 XML_SCHEMA_TYPE_SEQUENCE)))
12356 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012357 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12358 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012359 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012360 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012361 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012362 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012363 else {
12364 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012365 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012366 XML_SCHEMA_CONTENT_ELEMENTS;
12367 }
12368 } else {
12369 /*
12370 * SimpleType restriction.
12371 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012372 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012373 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012374 break;
12375 }
12376 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012377 xmlSchemaTypePtr base = NULL;
12378 xmlSchemaContentType explicitContentType;
12379
12380 /*
12381 * An extension does exist on a complexType only.
12382 */
12383 ctxt->ctxtType->flags |=
12384 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012385 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012386 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012387 xmlSchemaPCustomErr(ctxt,
12388 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012389 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012390 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012391 return;
12392 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012393 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012394 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012395 xmlSchemaGetType(ctxt->schema, item->base,
12396 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012397 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012398 xmlSchemaPResCompAttrErr(ctxt,
12399 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012400 NULL, item, item->node,
12401 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012402 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012403 } else if (base->contentType ==
12404 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012405 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012406 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012407 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012408 }
12409 /*
12410 * The type definition ·resolved· to by the ·actual
12411 * value· of the base [attribute]
12412 */
12413 ctxt->ctxtType->baseType = base;
12414 /*
12415 * TODO: This one is still needed for computation of
12416 * the content model by xmlSchemaBuildAContentModel.
12417 * Try to get rid of it.
12418 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012419 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012420 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012421 if ((item->subtypes != NULL) &&
12422 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12423 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012424
12425 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012426 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012427 /* 1.1.1 */
12428 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012429 else if ((item->subtypes->subtypes == NULL) &&
12430 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012431 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012432 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012433 XML_SCHEMA_TYPE_SEQUENCE)))
12434 /* 1.1.2 */
12435 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012436 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012437 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012438 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012439 /* 1.1.3 */
12440 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12441 if (base != NULL) {
12442 /* It will be reported later, if the base is missing. */
12443 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12444 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012445 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012446 } else if (base->contentType ==
12447 XML_SCHEMA_CONTENT_EMPTY) {
12448 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012449 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012450 XML_SCHEMA_CONTENT_ELEMENTS;
12451 } else {
12452 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012453 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012454 XML_SCHEMA_CONTENT_ELEMENTS;
12455 }
12456 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012457 break;
12458 }
12459 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012460 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012461 ctxt->ctxtType = item;
12462 /*
12463 * Start with an empty content-type type.
12464 */
12465 if (item->subtypes == NULL)
12466 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12467
12468 if ((item->subtypes == NULL) ||
12469 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012470 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012471 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012472 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12473 /*
12474 * This case is understood as shorthand for complex
12475 * content restricting the ur-type definition, and
12476 * the details of the mappings should be modified as
12477 * necessary.
12478 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012479 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12480 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012481 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012482 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012483 * Assume that we inherit the content-type type
12484 * from 'anyType', which is 'mixed' and a particle
12485 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012486 */
12487 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012488 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012489 /*
12490 * Fixup the sub components.
12491 */
12492 if ((item->subtypes != NULL) &&
12493 (item->subtypes->contentType ==
12494 XML_SCHEMA_CONTENT_UNKNOWN)) {
12495 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012496 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012497 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12498 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12499 } else if (item->subtypes != NULL) {
12500 /*
12501 * Use the content-type type of the model groups
12502 * defined, if 'mixed' is not set. If 'mixed' is set
12503 * it will expand the content-type by allowing character
12504 * content to appear.
12505 */
12506 item->contentType =
12507 item->subtypes->contentType;
12508 }
12509 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012510 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012511 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012512 break;
12513 }
12514 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012515 if (item->subtypes == NULL) {
12516 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12517 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12518 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012519 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012520 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012521 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12522 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012523 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012524 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012525 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012526 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012527 if (item->subtypes != NULL)
12528 item->contentType =
12529 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012530 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012531 /*
12532 * Removed due to implementation of the build of attribute uses.
12533 */
12534 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012535 if (item->attributes == NULL)
12536 item->attributes =
12537 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012538 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012539 }
12540 break;
12541 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012542 case XML_SCHEMA_TYPE_SIMPLE:
12543 /*
12544 * Simple Type Definition Schema Component
12545 *
12546 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012547 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012548 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12549 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012550 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012551 ctxt->ctxtType = item;
12552 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012553 }
12554 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012555 if ((item->baseType != NULL) &&
12556 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 XML_SCHEMA_CONTENT_UNKNOWN)) {
12558 /* OPTIMIZE: Actually this one will never by hit, since
12559 * the base type is already type-fixed in <restriction>.
12560 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012561 ctxt->ctxtType = item;
12562 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012563 }
12564 /* Base type:
12565 * 2 If the <list> or <union> alternative is chosen,
12566 * then the ·simple ur-type definition·.
12567 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012568 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012569 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012570 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12571 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12572 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012573 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012574 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12575 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12576 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012577 XML_SCHEMA_TYPE_RESTRICTION) {
12578 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12579
12580 /*
12581 * Variety
12582 * If the <restriction> alternative is chosen, then the
12583 * {variety} of the {base type definition}.
12584 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012585 if (item->baseType != NULL) {
12586 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012587 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012588 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12589 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012590 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012591 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12592 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012593 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012594 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012595 /*
12596 * Schema Component Constraint: Simple Type Restriction
12597 * (Facets)
12598 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12599 * applied beforehand.
12600 *
12601 * 3 The {facets} of R are the union of S and the {facets}
12602 * of B, eliminating duplicates. To eliminate duplicates,
12603 * when a facet of the same kind occurs in both S and the
12604 * {facets} of B, the one in the {facets} of B is not
12605 * included, with the exception of enumeration and pattern
12606 * facets, for which multiple occurrences with distinct values
12607 * are allowed.
12608 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012609 if (item->baseType->facetSet != NULL) {
12610 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012611 if (last != NULL)
12612 while (last->next != NULL)
12613 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012614 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012615 for (; cur != NULL; cur = cur->next) {
12616 /*
12617 * Base patterns won't be add here:
12618 * they are ORed in a type and
12619 * ANDed in derived types. This will
12620 * happed at validation level by
12621 * walking the base axis of the type.
12622 */
12623 if (cur->facet->type ==
12624 XML_SCHEMA_FACET_PATTERN)
12625 continue;
12626 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012627 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012628 (cur->facet->type !=
12629 XML_SCHEMA_FACET_PATTERN) &&
12630 (cur->facet->type !=
12631 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012632 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012633 do {
12634 if (cur->facet->type ==
12635 facet->facet->type)
12636 break;
12637 facet = facet->next;
12638 } while (facet != NULL);
12639 }
12640 if (facet == NULL) {
12641 facet = (xmlSchemaFacetLinkPtr)
12642 xmlMalloc(sizeof(xmlSchemaFacetLink));
12643 if (facet == NULL) {
12644 xmlSchemaPErrMemory(ctxt,
12645 "fixing simpleType", NULL);
12646 return;
12647 }
12648 facet->facet = cur->facet;
12649 facet->next = NULL;
12650 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012651 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012652 else
12653 last->next = facet;
12654 last = facet;
12655 }
12656 }
12657 }
12658 }
12659 }
12660 /*
12661 * Check constraints.
12662 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012663 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012664 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012665 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012666 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012667 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012668 case XML_SCHEMA_TYPE_ALL:
12669 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012670 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012671 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012672 case XML_SCHEMA_TYPE_GROUP:
12673 /*
12674 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12675 */
12676 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012677 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012678 xmlSchemaParseListRefFixup(item, ctxt);
12679 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012680 break;
12681 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012682 xmlSchemaParseUnionRefCheck(item, ctxt);
12683 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012684 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012685 case XML_SCHEMA_TYPE_BASIC:
12686 case XML_SCHEMA_TYPE_ANY:
12687 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012688 case XML_SCHEMA_TYPE_UR:
12689 case XML_SCHEMA_TYPE_ELEMENT:
12690 case XML_SCHEMA_TYPE_ATTRIBUTE:
12691 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012692 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012693 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012694 case XML_SCHEMA_FACET_MININCLUSIVE:
12695 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12696 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12697 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12698 case XML_SCHEMA_FACET_TOTALDIGITS:
12699 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12700 case XML_SCHEMA_FACET_PATTERN:
12701 case XML_SCHEMA_FACET_ENUMERATION:
12702 case XML_SCHEMA_FACET_WHITESPACE:
12703 case XML_SCHEMA_FACET_LENGTH:
12704 case XML_SCHEMA_FACET_MAXLENGTH:
12705 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012706 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12707 if (item->subtypes != NULL)
12708 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012709 break;
12710 }
12711 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012712#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012713 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012714 xmlGenericError(xmlGenericErrorContext,
12715 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012716 item->node->doc->URL,
12717 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012718 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012719 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012720 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012721 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012722 case XML_SCHEMA_CONTENT_SIMPLE:
12723 xmlGenericError(xmlGenericErrorContext, "simple\n");
12724 break;
12725 case XML_SCHEMA_CONTENT_ELEMENTS:
12726 xmlGenericError(xmlGenericErrorContext, "elements\n");
12727 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012728 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012729 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12730 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012731 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012732 xmlGenericError(xmlGenericErrorContext, "empty\n");
12733 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012734 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012735 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12736 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012737 /* Removed, since not used. */
12738 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012739 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012740 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12741 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012742 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012743 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012744 xmlGenericError(xmlGenericErrorContext, "basic\n");
12745 break;
12746 default:
12747 xmlGenericError(xmlGenericErrorContext,
12748 "not registered !!!\n");
12749 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012750 }
12751#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012752}
12753
12754/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012755 * xmlSchemaCheckFacet:
12756 * @facet: the facet
12757 * @typeDecl: the schema type definition
12758 * @ctxt: the schema parser context or NULL
12759 * @name: name of the type
12760 *
12761 * Checks the default values types, especially for facets
12762 *
12763 * Returns 0 if okay or -1 in cae of error
12764 */
12765int
12766xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012767 xmlSchemaTypePtr typeDecl,
12768 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012769{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012770 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012771 int ret = 0, reuseValCtxt = 0;
12772
Daniel Veillardce682bc2004-11-05 17:22:25 +000012773 if ((facet == NULL) || (typeDecl == NULL))
12774 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012775 /*
12776 * TODO: will the parser context be given if used from
12777 * the relaxNG module?
12778 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012779
12780 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012781 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012782 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012783 }
12784 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012785 case XML_SCHEMA_FACET_MININCLUSIVE:
12786 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12787 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012788 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12789 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012790 /*
12791 * Okay we need to validate the value
12792 * at that point.
12793 */
12794 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012795 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012796
12797 /* 4.3.5.5 Constraints on enumeration Schema Components
12798 * Schema Component Constraint: enumeration valid restriction
12799 * It is an ·error· if any member of {value} is not in the
12800 * ·value space· of {base type definition}.
12801 *
12802 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12803 * The value ·must· be in the
12804 * ·value space· of the ·base type·.
12805 */
12806 /*
12807 * This function is intended to deliver a compiled value
12808 * on the facet. In XML Schemas the type holding a facet,
12809 * cannot be a built-in type. Thus to ensure that other API
12810 * calls (relaxng) do work, if the given type is a built-in
12811 * type, we will assume that the given built-in type *is
12812 * already* the base type.
12813 */
12814 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12815 base = typeDecl->baseType;
12816 if (base == NULL) {
12817 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012818 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012819 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012820 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012821 typeDecl->name, NULL);
12822 return (-1);
12823 }
12824 } else
12825 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012826 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012827 * This avoids perseverative creation of the
12828 * validation context if a parser context is
12829 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012830 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012831 if (ctxt != NULL) {
12832 reuseValCtxt = 1;
12833 if (ctxt->vctxt == NULL) {
12834 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12835 return (-1);
12836 }
12837 vctxt = ctxt->vctxt;
12838 } else {
12839 vctxt = xmlSchemaNewValidCtxt(NULL);
12840 if (vctxt == NULL) {
12841 xmlSchemaPErr(ctxt, typeDecl->node,
12842 XML_SCHEMAP_INTERNAL,
12843 "Internal error: xmlSchemaCheckFacet, "
12844 "creating a new validation context.\n",
12845 NULL, NULL);
12846 return (-1);
12847 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012848 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012849
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012850 vctxt->node = facet->node;
12851 vctxt->cur = NULL;
12852 /*
12853 * NOTE: This call does not check the content nodes,
12854 * since they are not available:
12855 * facet->node is just the node holding the facet
12856 * definition, *not* the attribute holding the *value*
12857 * of the facet.
12858 */
12859 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12860 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012861 facet->val = vctxt->value;
12862 vctxt->value = NULL;
12863 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012864 /* error code */
12865 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012866 xmlSchemaPErrExt(ctxt, facet->node,
12867 XML_SCHEMAP_INVALID_FACET,
12868 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012869 "Type definition '%s': The value '%s' of the "
12870 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012871 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012872 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012873 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012874 }
12875 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012876 } else if (ret < 0) {
12877 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012878 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012879 NULL, NULL, NULL,
12880 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012881 "failed to validate the value '%s' name of the "
12882 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012883 facet->value,
12884 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12885 base->name, NULL, NULL);
12886 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012887 }
12888 if (reuseValCtxt == 0)
12889 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012890 break;
12891 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012892 case XML_SCHEMA_FACET_PATTERN:
12893 facet->regexp = xmlRegexpCompile(facet->value);
12894 if (facet->regexp == NULL) {
12895 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012896 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012897 "Type definition '%s': The value '%s' of the "
12898 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012899 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012900 ret = -1;
12901 }
12902 break;
12903 case XML_SCHEMA_FACET_TOTALDIGITS:
12904 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12905 case XML_SCHEMA_FACET_LENGTH:
12906 case XML_SCHEMA_FACET_MAXLENGTH:
12907 case XML_SCHEMA_FACET_MINLENGTH:{
12908 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012909
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012910 tmp =
12911 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12912 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012913 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012914 if (tmp != 0) {
12915 /* error code */
12916 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012917 xmlSchemaPErrExt(ctxt, facet->node,
12918 XML_SCHEMAP_INVALID_FACET_VALUE,
12919 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012920 "Type definition '%s': The value '%s' of the "
12921 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012922 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012923 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012924 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012925 }
12926 ret = -1;
12927 }
12928 break;
12929 }
12930 case XML_SCHEMA_FACET_WHITESPACE:{
12931 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12932 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12933 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12934 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12935 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12936 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12937 } else {
12938 if (ctxt != NULL) {
12939 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012940 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012941 "Type definition '%s': The value '%s' of the "
12942 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012943 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012944 }
12945 ret = -1;
12946 }
12947 }
12948 default:
12949 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012950 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012951 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012952}
12953
12954/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012955 * xmlSchemaCheckDefaults:
12956 * @typeDecl: the schema type definition
12957 * @ctxt: the schema parser context
12958 *
12959 * Checks the default values types, especially for facets
12960 */
12961static void
12962xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012963 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012964{
Daniel Veillard4255d502002-04-16 15:50:10 +000012965 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012966 name = typeDecl->name;
12967 /*
12968 * NOTE: It is intended to use the facets list, instead
12969 * of facetSet.
12970 */
12971 if (typeDecl->facets != NULL) {
12972 xmlSchemaFacetPtr facet = typeDecl->facets;
12973
12974 while (facet != NULL) {
12975 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12976 facet = facet->next;
12977 }
12978 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012979}
12980
12981/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012982 * xmlSchemaGetCircModelGrDefRef:
12983 * @ctxtGr: the searched model group
12984 * @list: the list of model groups to be processed
12985 *
12986 * This one is intended to be used by
12987 * xmlSchemaCheckGroupDefCircular only.
12988 *
12989 * Returns the circular model group definition reference, otherwise NULL.
12990 */
12991static xmlSchemaTypePtr
12992xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12993 xmlSchemaTypePtr gr)
12994{
12995 xmlSchemaTypePtr circ = NULL;
12996 int marked;
12997 /*
12998 * We will search for an model group reference which
12999 * references the context model group definition.
13000 */
13001 while (gr != NULL) {
13002 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13003 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13004 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13005 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13006 (gr->subtypes != NULL)) {
13007 marked = 0;
13008 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13009 (gr->ref != NULL)) {
13010 if (gr->subtypes == ctxtGrDef)
13011 return (gr);
13012 else if (gr->subtypes->flags &
13013 XML_SCHEMAS_TYPE_MARKED) {
13014 gr = gr->next;
13015 continue;
13016 } else {
13017 /*
13018 * Mark to avoid infinite recursion on
13019 * circular references not yet examined.
13020 */
13021 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13022 marked = 1;
13023 }
13024 if (gr->subtypes->subtypes != NULL)
13025 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13026 gr->subtypes->subtypes);
13027 /*
13028 * Unmark the visited model group definition.
13029 */
13030 if (marked)
13031 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13032 if (circ != NULL)
13033 return (circ);
13034 } else {
13035 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13036 (xmlSchemaTypePtr) gr->subtypes);
13037 if (circ != NULL)
13038 return (circ);
13039 }
13040
13041 }
13042 gr = gr->next;
13043 }
13044 return (NULL);
13045}
13046
13047/**
13048 * xmlSchemaCheckGroupDefCircular:
13049 * attrGr: the model group definition
13050 * @ctxt: the parser context
13051 * @name: the name
13052 *
13053 * Checks for circular references to model group definitions.
13054 */
13055static void
13056xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13057 xmlSchemaParserCtxtPtr ctxt,
13058 const xmlChar * name ATTRIBUTE_UNUSED)
13059{
13060 /*
13061 * Schema Component Constraint: Model Group Correct
13062 * 2 Circular groups are disallowed. That is, within the {particles}
13063 * of a group there must not be at any depth a particle whose {term}
13064 * is the group itself.
13065 */
13066 /*
13067 * NOTE: "gr->subtypes" holds the referenced group.
13068 */
13069 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13070 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13071 (modelGrDef->subtypes == NULL))
13072 return;
13073 else {
13074 xmlSchemaTypePtr circ;
13075
13076 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13077 if (circ != NULL) {
13078 /*
13079 * TODO: Report the referenced attr group as QName.
13080 */
13081 xmlSchemaPCustomErr(ctxt,
13082 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13083 NULL, NULL, circ->node,
13084 "Circular reference to the model group definition '%s' "
13085 "defined", modelGrDef->name);
13086 /*
13087 * NOTE: We will cut the reference to avoid further
13088 * confusion of the processor.
13089 * TODO: SPEC: Does the spec define how to process here?
13090 */
13091 circ->subtypes = NULL;
13092 }
13093 }
13094}
13095
13096
13097/**
13098 * xmlSchemaGetCircAttrGrRef:
13099 * @ctxtGr: the searched attribute group
13100 * @attr: the current attribute list to be processed
13101 *
13102 * This one is intended to be used by
13103 * xmlSchemaCheckSRCAttributeGroupCircular only.
13104 *
13105 * Returns the circular attribute grou reference, otherwise NULL.
13106 */
13107static xmlSchemaAttributeGroupPtr
13108xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
13109 xmlSchemaAttributePtr attr)
13110{
13111 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13112 int marked;
13113 /*
13114 * We will search for an attribute group reference which
13115 * references the context attribute group.
13116 */
13117 while (attr != NULL) {
13118 marked = 0;
13119 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13120 gr = (xmlSchemaAttributeGroupPtr) attr;
13121 if (gr->refItem != NULL) {
13122 if (gr->refItem == ctxtGr)
13123 return (gr);
13124 else if (gr->refItem->flags &
13125 XML_SCHEMAS_ATTRGROUP_MARKED) {
13126 attr = attr->next;
13127 continue;
13128 } else {
13129 /*
13130 * Mark as visited to avoid infinite recursion on
13131 * circular references not yet examined.
13132 */
13133 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
13134 marked = 1;
13135 }
13136 }
13137 if (gr->attributes != NULL)
13138 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
13139 /*
13140 * Unmark the visited group's attributes.
13141 */
13142 if (marked)
13143 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
13144 if (circ != NULL)
13145 return (circ);
13146 }
13147 attr = attr->next;
13148 }
13149 return (NULL);
13150}
13151
13152/**
13153 * xmlSchemaCheckSRCAttributeGroupCircular:
13154 * attrGr: the attribute group definition
13155 * @ctxt: the parser context
13156 * @name: the name
13157 *
13158 * Checks for circular references of attribute groups.
13159 */
13160static void
13161xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
13162 xmlSchemaParserCtxtPtr ctxt,
13163 const xmlChar * name ATTRIBUTE_UNUSED)
13164{
13165 /*
13166 * Schema Representation Constraint:
13167 * Attribute Group Definition Representation OK
13168 * 3 Circular group reference is disallowed outside <redefine>.
13169 * That is, unless this element information item's parent is
13170 * <redefine>, then among the [children], if any, there must
13171 * not be an <attributeGroup> with ref [attribute] which resolves
13172 * to the component corresponding to this <attributeGroup>. Indirect
13173 * circularity is also ruled out. That is, when QName resolution
13174 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13175 * any <attributeGroup>s with a ref [attribute] among the [children],
13176 * it must not be the case that a ·QName· is encountered at any depth
13177 * which resolves to the component corresponding to this <attributeGroup>.
13178 */
13179 /*
13180 * Only global components can be referenced.
13181 */
13182 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
13183 (attrGr->attributes == NULL))
13184 return;
13185 else {
13186 xmlSchemaAttributeGroupPtr circ;
13187
13188 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
13189 if (circ != NULL) {
13190 /*
13191 * TODO: Report the referenced attr group as QName.
13192 */
13193 xmlSchemaPCustomErr(ctxt,
13194 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13195 NULL, NULL, circ->node,
13196 "Circular reference to the attribute group '%s' "
13197 "defined", attrGr->name);
13198 /*
13199 * NOTE: We will cut the reference to avoid further
13200 * confusion of the processor.
13201 * BADSPEC: The spec should define how to process in this case.
13202 */
13203 circ->attributes = NULL;
13204 circ->refItem = NULL;
13205 }
13206 }
13207}
13208
13209/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013210 * xmlSchemaAttrGrpFixup:
13211 * @attrgrpDecl: the schema attribute definition
13212 * @ctxt: the schema parser context
13213 * @name: the attribute name
13214 *
13215 * Fixes finish doing the computations on the attributes definitions
13216 */
13217static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013218xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013219 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013220{
13221 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013222 name = attrgrp->name;
13223 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013224 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013225 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013226 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013227
Daniel Veillardc0826a72004-08-10 14:17:33 +000013228 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13229 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013230 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013231 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013232 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013233 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13234 "ref", attrgrp->ref, attrgrp->refNs,
13235 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013236 return;
13237 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013238 attrgrp->refItem = ref;
13239 /*
13240 * Check for self reference!
13241 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013242 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013243 attrgrp->attributes = ref->attributes;
13244 attrgrp->attributeWildcard = ref->attributeWildcard;
13245 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013246}
13247
13248/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013249 * xmlSchemaAttrCheckValConstr:
13250 * @item: an schema attribute declaration/use
13251 * @ctxt: a schema parser context
13252 * @name: the name of the attribute
13253 *
13254 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013255 *
13256 * Fixes finish doing the computations on the attributes definitions
13257 */
13258static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013259xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13260 xmlSchemaParserCtxtPtr ctxt,
13261 const xmlChar * name ATTRIBUTE_UNUSED)
13262{
13263
13264 /*
13265 * a-props-correct
13266 * Schema Component Constraint: Attribute Declaration Properties Correct
13267 *
13268 * 2 if there is a {value constraint}, the canonical lexical
13269 * representation of its value must be ·valid· with respect
13270 * to the {type definition} as defined in String Valid (§3.14.4).
13271 */
13272
13273 if (item->defValue != NULL) {
13274 int ret;
13275 xmlNodePtr node;
13276 xmlSchemaTypePtr type;
13277
13278 if (item->subtypes == NULL) {
13279 xmlSchemaPErr(ctxt, item->node,
13280 XML_SCHEMAP_INTERNAL,
13281 "Internal error: xmlSchemaCheckAttrValConstr, "
13282 "type is missing... skipping validation of "
13283 "value constraint", NULL, NULL);
13284 return;
13285 }
13286
13287 /*
13288 * TODO: Try to avoid creating a new context.
13289 * TODO: This all is not very performant.
13290 */
13291 type = item->subtypes;
13292 /*
13293 * Ensure there's validation context.
13294 */
13295 if (ctxt->vctxt == NULL) {
13296 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13297 xmlSchemaPErr(ctxt, item->node,
13298 XML_SCHEMAP_INTERNAL,
13299 "Internal error: xmlSchemaCheckAttrValConstr, "
13300 "creating a new validation context.\n",
13301 NULL, NULL);
13302 return;
13303 }
13304 }
13305
13306 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13307 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13308 else
13309 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13310 ctxt->vctxt->node = node;
13311 ctxt->vctxt->cur = NULL;
13312 /*
13313 * NOTE: This call does not check the content nodes,
13314 * since they are not available:
13315 * facet->node is just the node holding the facet
13316 * definition, *not* the attribute holding the *value*
13317 * of the facet.
13318 */
13319 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13320 item->defValue, 0, 1, 1, 0);
13321 if (ret == 0) {
13322 /*
13323 * Store the computed value.
13324 */
13325 item->defVal = ctxt->vctxt->value;
13326 ctxt->vctxt->value = NULL;
13327 } else if (ret > 0) {
13328 if (ctxt != NULL) {
13329 xmlSchemaPSimpleTypeErr(ctxt,
13330 XML_SCHEMAP_A_PROPS_CORRECT_2,
13331 NULL, NULL, node,
13332 type, NULL, item->defValue,
13333 NULL, NULL, NULL);
13334 }
13335 } else if (ret < 0) {
13336 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13337 NULL, NULL, node,
13338 "Internal error: xmlSchemaAttrCheckValConstr, "
13339 "failed to validate the value constraint of the "
13340 "attribute decl/use against the type '%s'",
13341 type->name);
13342 }
13343 }
13344}
13345
13346#if 0 /* Not used yet. */
13347static int
13348xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13349 xmlSchemaElementPtr edecl)
13350{
13351 /*
13352 * TODO: 1 The values of the properties of an element declaration must be as
13353 * described in the property tableau in The Element Declaration Schema
13354 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13355 */
13356 /*
13357 * 2 If there is a {value constraint}, the canonical lexical
13358 * representation of its value must be ·valid· with respect to the {type
13359 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13360 *
13361 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13362 */
13363 /*
13364 * 3 If there is a non-·absent· {substitution group affiliation},
13365 * then {scope} must be global.
13366 *
13367 * NOTE: This is done in xmlSchemaParseElement.
13368 * TODO: Move it to this layer here.
13369 */
13370 /*
13371 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13372 * of the element declaration must be validly derived from the {type
13373 * definition} of the {substitution group affiliation}, given the value
13374 * of the {substitution group exclusions} of the {substitution group
13375 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13376 * (if the {type definition} is complex) or as defined in
13377 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13378 * simple).
13379 */
13380 /*
13381 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13382 * is or is derived from ID then there must not be a {value constraint}.
13383 * Note: The use of ID as a type definition for elements goes beyond
13384 * XML 1.0, and should be avoided if backwards compatibility is desired
13385 */
13386 /*
13387 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13388 * be possible to return to an element declaration by repeatedly following
13389 * the {substitution group affiliation} property.
13390 */
13391}
13392#endif
13393
13394/**
13395 * xmlSchemaCheckElemValConstr:
13396 * @item: an schema element declaration/particle
13397 * @ctxt: a schema parser context
13398 * @name: the name of the attribute
13399 *
13400 * Validates the value constraints of an element declaration.
13401 *
13402 * Fixes finish doing the computations on the element declarations.
13403 */
13404static void
13405xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13406 xmlSchemaParserCtxtPtr ctxt,
13407 const xmlChar * name ATTRIBUTE_UNUSED)
13408{
13409 if (decl->value != NULL) {
13410 int ret;
13411 xmlNodePtr node = NULL;
13412 xmlSchemaTypePtr type;
13413
13414 /*
13415 * 2 If there is a {value constraint}, the canonical lexical
13416 * representation of its value must be ·valid· with respect to the {type
13417 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13418 */
13419 if (decl->subtypes == NULL) {
13420 xmlSchemaPErr(ctxt, decl->node,
13421 XML_SCHEMAP_INTERNAL,
13422 "Internal error: xmlSchemaCheckElemValConstr, "
13423 "type is missing... skipping validation of "
13424 "the value constraint", NULL, NULL);
13425 return;
13426 }
13427 /*
13428 * Ensure there's a validation context.
13429 */
13430 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13431 return;
13432
13433 type = decl->subtypes;
13434
13435 if (decl->node != NULL) {
13436 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13437 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13438 else
13439 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13440 }
13441 ctxt->vctxt->node = node;
13442 ctxt->vctxt->cur = NULL;
13443 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13444 node);
13445 if (ret == 0) {
13446 /*
13447 * Consume the computed value.
13448 */
13449 decl->defVal = ctxt->vctxt->value;
13450 ctxt->vctxt->value = NULL;
13451 } else if (ret < 0) {
13452 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13453 NULL, NULL, node,
13454 "Internal error: xmlSchemaElemCheckValConstr, "
13455 "failed to validate the value constraint of the "
13456 "element declaration '%s'",
13457 decl->name);
13458 }
13459 }
13460}
13461
13462/**
13463 * xmlSchemaAttrFixup:
13464 * @item: an schema attribute declaration/use.
13465 * @ctxt: a schema parser context
13466 * @name: the name of the attribute
13467 *
13468 * Fixes finish doing the computations on attribute declarations/uses.
13469 */
13470static void
13471xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13472 xmlSchemaParserCtxtPtr ctxt,
13473 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013474{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013475 /*
13476 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013477 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013478 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 /*
13480 * The simple type definition corresponding to the <simpleType> element
13481 * information item in the [children], if present, otherwise the simple
13482 * type definition ·resolved· to by the ·actual value· of the type
13483 * [attribute], if present, otherwise the ·simple ur-type definition·.
13484 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013485 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013486 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013487 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13488 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013489 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013490 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013491 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013492
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013493 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13494 item->typeNs);
13495 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013496 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013497 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013498 NULL, (xmlSchemaTypePtr) item, item->node,
13499 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013500 XML_SCHEMA_TYPE_SIMPLE, NULL);
13501 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013502 item->subtypes = type;
13503
13504 } else if (item->ref != NULL) {
13505 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013506
Daniel Veillardc0826a72004-08-10 14:17:33 +000013507 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013508 * We have an attribute use here; assign the referenced
13509 * attribute declaration.
13510 */
13511 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013512 * TODO: Evaluate, what errors could occur if the declaration is not
13513 * found. It might be possible that the "typefixup" might crash if
13514 * no ref declaration was found.
13515 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013516 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13517 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013518 xmlSchemaPResCompAttrErr(ctxt,
13519 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013520 NULL, (xmlSchemaTypePtr) item, item->node,
13521 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013522 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013523 return;
13524 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013525 item->refDecl = decl;
13526 xmlSchemaAttrFixup(decl, ctxt, NULL);
13527
13528 item->subtypes = decl->subtypes;
13529 /*
13530 * Attribute Use Correct
13531 * au-props-correct.2: If the {attribute declaration} has a fixed
13532 * {value constraint}, then if the attribute use itself has a
13533 * {value constraint}, it must also be fixed and its value must match
13534 * that of the {attribute declaration}'s {value constraint}.
13535 */
13536 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13537 (item->defValue != NULL)) {
13538 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13539 (!xmlStrEqual(item->defValue, decl->defValue))) {
13540 xmlSchemaPCustomErr(ctxt,
13541 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13542 NULL, NULL, item->node,
13543 "The value constraint must be fixed "
13544 "and match the referenced attribute "
13545 "declarations's value constraint '%s'",
13546 decl->defValue);
13547 }
13548 /*
13549 * FUTURE: One should change the values of the attr. use
13550 * if ever validation should be attempted even if the
13551 * schema itself was not fully valid.
13552 */
13553 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013554 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013555 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13556 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013557}
13558
13559/**
13560 * xmlSchemaParse:
13561 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013562 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013563 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013564 * XML Shema struture which can be used to validate instances.
13565 * *WARNING* this interface is highly subject to change
13566 *
13567 * Returns the internal XML Schema structure built from the resource or
13568 * NULL in case of error
13569 */
13570xmlSchemaPtr
13571xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13572{
13573 xmlSchemaPtr ret = NULL;
13574 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013575 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013576 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013577
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013578 /*
13579 * This one is used if the schema to be parsed was specified via
13580 * the API; i.e. not automatically by the validated instance document.
13581 */
13582
Daniel Veillard4255d502002-04-16 15:50:10 +000013583 xmlSchemaInitTypes();
13584
Daniel Veillard6045c902002-10-09 21:13:59 +000013585 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013586 return (NULL);
13587
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013588 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013589 ctxt->counter = 0;
13590 ctxt->container = NULL;
13591
13592 /*
13593 * First step is to parse the input document into an DOM/Infoset
13594 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013595 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013596 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13597 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013598 if (doc == NULL) {
13599 xmlSchemaPErr(ctxt, NULL,
13600 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013601 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013602 ctxt->URL, NULL);
13603 return (NULL);
13604 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013605 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013606 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13607 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013608 if (doc == NULL) {
13609 xmlSchemaPErr(ctxt, NULL,
13610 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013611 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013612 NULL, NULL);
13613 return (NULL);
13614 }
13615 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013616 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013617 } else if (ctxt->doc != NULL) {
13618 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013619 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013620 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013621 xmlSchemaPErr(ctxt, NULL,
13622 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013623 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013624 NULL, NULL);
13625 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013626 }
13627
13628 /*
13629 * Then extract the root and Schema parse it
13630 */
13631 root = xmlDocGetRootElement(doc);
13632 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013633 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13634 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013635 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013636 if (!preserve) {
13637 xmlFreeDoc(doc);
13638 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013639 return (NULL);
13640 }
13641
13642 /*
13643 * Remove all the blank text nodes
13644 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013645 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013646
13647 /*
13648 * Then do the parsing for good
13649 */
13650 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013651 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013652 if (!preserve) {
13653 xmlFreeDoc(doc);
13654 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013655 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013656 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013657 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013658 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013659 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013660 ctxt->ctxtType = NULL;
13661 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013662 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013663 * Then fixup all attributes declarations
13664 */
13665 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13666
13667 /*
13668 * Then fixup all attributes group declarations
13669 */
13670 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13671 ctxt);
13672
13673 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013674 * Check attribute groups for circular references.
13675 */
13676 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13677 xmlSchemaCheckAttributeGroupCircular, ctxt);
13678
13679 /*
13680 * Then fixup all model group definitions.
13681 */
13682 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013683
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013684 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013685 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013686 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013687 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013688
13689 /*
13690 * Then fix references of element declaration; apply constraints.
13691 */
13692 xmlHashScanFull(ret->elemDecl,
13693 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013694
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013695 /*
13696 * Check model groups defnitions for circular references.
13697 */
13698 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13699 xmlSchemaCheckGroupDefCircular, ctxt);
13700
Daniel Veillard4255d502002-04-16 15:50:10 +000013701 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013702 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013703 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013704 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013705 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013706
13707 /*
13708 * Then check the defaults part of the type like facets values
13709 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013710 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000013711
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013712 /*
13713 * Validate the value constraint of attribute declarations/uses.
13714 */
13715 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13716
13717 /*
13718 * Validate the value constraint of element declarations.
13719 */
13720 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13721
Daniel Veillardc0826a72004-08-10 14:17:33 +000013722
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013723 if (ctxt->nberrors != 0) {
13724 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013725 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013726 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013727 return (ret);
13728}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013729
Daniel Veillard4255d502002-04-16 15:50:10 +000013730/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013731 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013732 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013733 * @err: the error callback
13734 * @warn: the warning callback
13735 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013736 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013737 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013738 */
13739void
13740xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013741 xmlSchemaValidityErrorFunc err,
13742 xmlSchemaValidityWarningFunc warn, void *ctx)
13743{
Daniel Veillard4255d502002-04-16 15:50:10 +000013744 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013745 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013746 ctxt->error = err;
13747 ctxt->warning = warn;
13748 ctxt->userData = ctx;
13749}
13750
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013751/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013752 * xmlSchemaGetParserErrors:
13753 * @ctxt: a XMl-Schema parser context
13754 * @err: the error callback result
13755 * @warn: the warning callback result
13756 * @ctx: contextual data for the callbacks result
13757 *
13758 * Get the callback information used to handle errors for a parser context
13759 *
13760 * Returns -1 in case of failure, 0 otherwise
13761 */
13762int
13763xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13764 xmlSchemaValidityErrorFunc * err,
13765 xmlSchemaValidityWarningFunc * warn, void **ctx)
13766{
13767 if (ctxt == NULL)
13768 return(-1);
13769 if (err != NULL)
13770 *err = ctxt->error;
13771 if (warn != NULL)
13772 *warn = ctxt->warning;
13773 if (ctx != NULL)
13774 *ctx = ctxt->userData;
13775 return(0);
13776}
13777
13778/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013779 * xmlSchemaFacetTypeToString:
13780 * @type: the facet type
13781 *
13782 * Convert the xmlSchemaTypeType to a char string.
13783 *
13784 * Returns the char string representation of the facet type if the
13785 * type is a facet and an "Internal Error" string otherwise.
13786 */
13787static const char *
13788xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13789{
13790 switch (type) {
13791 case XML_SCHEMA_FACET_PATTERN:
13792 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013793 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013794 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013795 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013796 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013797 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013798 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013799 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013800 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013801 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013802 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013803 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013804 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013805 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013806 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013807 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013808 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013809 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013810 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013811 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013812 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013813 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013814 return ("fractionDigits");
13815 default:
13816 break;
13817 }
13818 return ("Internal Error");
13819}
13820
Daniel Veillardc0826a72004-08-10 14:17:33 +000013821
Daniel Veillardc0826a72004-08-10 14:17:33 +000013822
13823static int
13824xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13825{
13826 xmlSchemaTypePtr anc;
13827
13828 /*
13829 * The normalization type can be changed only for types which are derived
13830 * from xsd:string.
13831 */
13832 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013833 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013834 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013835 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
13836 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013837 else {
13838 /*
13839 * For all ·atomic· datatypes other than string (and types ·derived·
13840 * by ·restriction· from it) the value of whiteSpace is fixed to
13841 * collapse
13842 */
13843 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13844 }
13845 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13846 /*
13847 * For list types the facet "whiteSpace" is fixed to "collapse".
13848 */
13849 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13850 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13851 return (-1);
13852 } else if (type->facetSet != NULL) {
13853 xmlSchemaTypePtr anyST;
13854 xmlSchemaFacetLinkPtr lin;
13855
13856 /*
13857 * Atomic types.
13858 */
13859 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13860 anc = type->baseType;
13861 do {
13862 /*
13863 * For all ·atomic· datatypes other than string (and types ·derived·
13864 * by ·restriction· from it) the value of whiteSpace is fixed to
13865 * collapse
13866 */
13867 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13868 (anc->builtInType == XML_SCHEMAS_STRING)) {
13869
13870 lin = type->facetSet;
13871 do {
13872 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13873 if (lin->facet->whitespace ==
13874 XML_SCHEMAS_FACET_COLLAPSE) {
13875 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13876 } else if (lin->facet->whitespace ==
13877 XML_SCHEMAS_FACET_REPLACE) {
13878 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13879 } else
13880 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13881 break;
13882 }
13883 lin = lin->next;
13884 } while (lin != NULL);
13885 break;
13886 }
13887 anc = anc->baseType;
13888 } while (anc != anyST);
13889 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13890 }
13891 return (-1);
13892}
13893
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013894/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013895 * xmlSchemaValidateFacetsInternal:
13896 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013897 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013898 * @facets: the list of facets to check
13899 * @value: the lexical repr of the value to validate
13900 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013901 * @fireErrors: if 0, only internal errors will be fired;
13902 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013903 *
13904 * Check a value against all facet conditions
13905 *
13906 * Returns 0 if the element is schemas valid, a positive error code
13907 * number otherwise and -1 in case of internal or API error.
13908 */
13909static int
13910xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013911 xmlSchemaTypePtr type,
13912 const xmlChar * value,
13913 unsigned long length,
13914 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013915{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013916 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013917 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013918 xmlSchemaTypePtr biType; /* The build-in type. */
13919 xmlSchemaTypePtr tmpType;
13920 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013921 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013922 xmlSchemaFacetPtr facet;
13923 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013924
Daniel Veillardc0826a72004-08-10 14:17:33 +000013925#ifdef DEBUG_UNION_VALIDATION
13926 printf("Facets of type: '%s'\n", (const char *) type->name);
13927 printf(" fireErrors: %d\n", fireErrors);
13928#endif
13929
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013930 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013931 /*
13932 * NOTE: Do not jump away, if the facetSet of the given type is
13933 * empty: until now, "pattern" facets of the *base types* need to
13934 * be checked as well.
13935 */
13936 biType = type->baseType;
13937 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13938 biType = biType->baseType;
13939 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013940 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013941 "Internal error: xmlSchemaValidateFacetsInternal, "
13942 "the base type axis of the given type '%s' does not resolve to "
13943 "a built-in type.\n",
13944 type->name, NULL);
13945 return (-1);
13946 }
13947
13948 if (type->facetSet != NULL) {
13949 facetLink = type->facetSet;
13950 while (facetLink != NULL) {
13951 facet = facetLink->facet;
13952 /*
13953 * Skip the pattern "whiteSpace": it is used to
13954 * format the character content beforehand.
13955 */
13956 switch (facet->type) {
13957 case XML_SCHEMA_FACET_WHITESPACE:
13958 case XML_SCHEMA_FACET_PATTERN:
13959 case XML_SCHEMA_FACET_ENUMERATION:
13960 break;
13961 case XML_SCHEMA_FACET_LENGTH:
13962 case XML_SCHEMA_FACET_MINLENGTH:
13963 case XML_SCHEMA_FACET_MAXLENGTH:
13964 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13965 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13966 value, length, 0);
13967 len = length;
13968 } else
13969 ret = xmlSchemaValidateLengthFacet(biType, facet,
13970 value, ctxt->value, &len);
13971 break;
13972 default:
13973 ret = xmlSchemaValidateFacet(biType, facet, value,
13974 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013975 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013976 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013977 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013978 "Internal error: xmlSchemaValidateFacetsInternal, "
13979 "validating facet of type '%s'.\n",
13980 type->name, NULL);
13981 break;
13982 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013983 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013984 type, facet, NULL, NULL, NULL, NULL);
13985 }
13986
13987 facetLink = facetLink->next;
13988 }
13989 if (ret >= 0) {
13990 /*
13991 * Process enumerations.
13992 */
13993 retFacet = 0;
13994 facetLink = type->facetSet;
13995 while (facetLink != NULL) {
13996 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
13997 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13998 value, ctxt->value);
13999 if (retFacet <= 0)
14000 break;
14001 }
14002 facetLink = facetLink->next;
14003 }
14004 if (retFacet > 0) {
14005 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14006 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014007 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014008 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14009 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014010 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014011 "Internal error: xmlSchemaValidateFacetsInternal, "
14012 "validating facet of type '%s'.\n",
14013 BAD_CAST "enumeration", NULL);
14014 ret = -1;
14015 }
14016 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014017 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014018 if (ret >= 0) {
14019 /*
14020 * Process patters. Pattern facets are ORed at type level
14021 * and ANDed if derived. Walk the base type axis.
14022 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014023 tmpType = type;
14024 facet = NULL;
14025 do {
14026 retFacet = 0;
14027 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014028 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014029 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14030 continue;
14031 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14032 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014033 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014034 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014035 else if (retFacet < 0) {
14036 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14037 "Internal error: xmlSchemaValidateFacetsInternal, "
14038 "validating 'pattern' facet '%s' of type '%s'.\n",
14039 facetLink->facet->value, tmpType->name);
14040 ret = -1;
14041 break;
14042 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014043 /* Save the last non-validating facet. */
14044 facet = facetLink->facet;
14045 }
14046 if (retFacet != 0)
14047 break;
14048 tmpType = tmpType->baseType;
14049 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014050 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014051 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14052 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014053 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014054 NULL, NULL, NULL, NULL);
14055 }
14056 }
14057 }
14058
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014059 return (ret);
14060}
14061
Daniel Veillard4255d502002-04-16 15:50:10 +000014062/************************************************************************
14063 * *
14064 * Simple type validation *
14065 * *
14066 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000014067
Daniel Veillard4255d502002-04-16 15:50:10 +000014068
14069/************************************************************************
14070 * *
14071 * DOM Validation code *
14072 * *
14073 ************************************************************************/
14074
Daniel Veillard4255d502002-04-16 15:50:10 +000014075static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014076 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000014077 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014078static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014079 xmlSchemaTypePtr type,
14080 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000014081
Daniel Veillard3646d642004-06-02 19:19:14 +000014082
14083/**
14084 * xmlSchemaFreeAttrStates:
14085 * @state: a list of attribute states
14086 *
14087 * Free the given list of attribute states
14088 *
14089 */
14090static void
14091xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
14092{
14093 xmlSchemaAttrStatePtr tmp;
14094 while (state != NULL) {
14095 tmp = state;
14096 state = state->next;
14097 xmlFree(tmp);
14098 }
14099}
14100
Daniel Veillard4255d502002-04-16 15:50:10 +000014101/**
14102 * xmlSchemaRegisterAttributes:
14103 * @ctxt: a schema validation context
14104 * @attrs: a list of attributes
14105 *
14106 * Register the list of attributes as the set to be validated on that element
14107 *
14108 * Returns -1 in case of error, 0 otherwise
14109 */
14110static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014111xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
14112{
Daniel Veillard3646d642004-06-02 19:19:14 +000014113 xmlSchemaAttrStatePtr tmp;
14114
14115 ctxt->attr = NULL;
14116 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014117 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014118 if ((attrs->ns != NULL) &&
14119 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
14120 attrs = attrs->next;
14121 continue;
14122 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014123 tmp = (xmlSchemaAttrStatePtr)
14124 xmlMalloc(sizeof(xmlSchemaAttrState));
14125 if (tmp == NULL) {
14126 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
14127 return (-1);
14128 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014129 tmp->attr = attrs;
14130 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
14131 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014132 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014133 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014134 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000014135 else
14136 ctxt->attrTop->next = tmp;
14137 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014138 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014139 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014140 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014141}
14142
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014143#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000014144/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014145 * xmlSchemaValidateCheckNodeList
14146 * @nodelist: the list of nodes
14147 *
14148 * Check the node list is only made of text nodes and entities pointing
14149 * to text nodes
14150 *
14151 * Returns 1 if true, 0 if false and -1 in case of error
14152 */
14153static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014154xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
14155{
Daniel Veillard4255d502002-04-16 15:50:10 +000014156 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014157 if (nodelist->type == XML_ENTITY_REF_NODE) {
14158 TODO /* implement recursion in the entity content */
14159 }
14160 if ((nodelist->type != XML_TEXT_NODE) &&
14161 (nodelist->type != XML_COMMENT_NODE) &&
14162 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000014163 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014164 return (0);
14165 }
14166 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014167 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014168 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014169}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014170#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014171
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014172static void
14173xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14174{
14175 int i, nbItems;
14176 xmlSchemaTypePtr item, *items;
14177
14178
14179 /*
14180 * During the Assemble of the schema ctxt->curItems has
14181 * been filled with the relevant new items. Fix those up.
14182 */
14183 nbItems = ctxt->assemble->nbItems;
14184 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14185
14186 for (i = 0; i < nbItems; i++) {
14187 item = items[i];
14188 switch (item->type) {
14189 case XML_SCHEMA_TYPE_ATTRIBUTE:
14190 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14191 break;
14192 case XML_SCHEMA_TYPE_ELEMENT:
14193 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14194 NULL, NULL, NULL);
14195 break;
14196 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14197 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14198 ctxt, NULL);
14199 break;
14200 case XML_SCHEMA_TYPE_GROUP:
14201 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14202 default:
14203 break;
14204 }
14205 }
14206 /*
14207 * Circularity checks.
14208 */
14209 for (i = 0; i < nbItems; i++) {
14210 item = items[i];
14211 switch (item->type) {
14212 case XML_SCHEMA_TYPE_GROUP:
14213 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14214 break;
14215 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14216 xmlSchemaCheckAttributeGroupCircular(
14217 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14218 break;
14219 default:
14220 break;
14221 }
14222 }
14223 /*
14224 * Fixup for all other item.
14225 * TODO: Hmm, not sure if starting from complex/simple types,
14226 * all subsequent items will be reached.
14227 */
14228 for (i = 0; i < nbItems; i++) {
14229 item = items[i];
14230 switch (item->type) {
14231 case XML_SCHEMA_TYPE_SIMPLE:
14232 case XML_SCHEMA_TYPE_COMPLEX:
14233 xmlSchemaTypeFixup(item, ctxt, NULL);
14234 break;
14235 default:
14236 break;
14237 }
14238 }
14239 /*
14240 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014241 * hold by simple type components only (and
14242 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014243 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014244 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014245 for (i = 0; i < nbItems; i++) {
14246 item = items[i];
14247 switch (item->type) {
14248 case XML_SCHEMA_TYPE_SIMPLE:
14249 case XML_SCHEMA_TYPE_COMPLEX:
14250 xmlSchemaCheckDefaults(item, ctxt, NULL);
14251 break;
14252 default:
14253 break;
14254 }
14255 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014256 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014257 /*
14258 * Build the content model for complex types.
14259 */
14260 for (i = 0; i < nbItems; i++) {
14261 item = items[i];
14262 switch (item->type) {
14263 case XML_SCHEMA_TYPE_COMPLEX:
14264 xmlSchemaBuildContentModel(item, ctxt, NULL);
14265 break;
14266 default:
14267 break;
14268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014269 }
14270 /*
14271 * Validate value contraint values.
14272 */
14273 for (i = 0; i < nbItems; i++) {
14274 item = items[i];
14275 switch (item->type) {
14276 case XML_SCHEMA_TYPE_ATTRIBUTE:
14277 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14278 break;
14279 case XML_SCHEMA_TYPE_ELEMENT:
14280 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14281 break;
14282 default:
14283 break;
14284 }
14285 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014286}
14287
14288/**
14289 * xmlSchemaAssembleByLocation:
14290 * @pctxt: a schema parser context
14291 * @vctxt: a schema validation context
14292 * @schema: the existing schema
14293 * @node: the node that fired the assembling
14294 * @nsName: the namespace name of the new schema
14295 * @location: the location of the schema
14296 *
14297 * Expands an existing schema by an additional schema.
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
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014303xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14304 xmlSchemaPtr schema,
14305 xmlNodePtr node,
14306 const xmlChar *nsName,
14307 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014308{
14309 const xmlChar *targetNs, *oldtns;
14310 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014311 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014312 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014313 xmlSchemaParserCtxtPtr pctxt;
14314
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014315 /*
14316 * This should be used:
14317 * 1. on <import>(s)
14318 * 2. if requested by the validated instance
14319 * 3. if requested via the API
14320 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014321 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014322 return (-1);
14323 /*
14324 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014325 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014326 if ((vctxt->pctxt == NULL) &&
14327 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14328 xmlSchemaVErr(vctxt, node,
14329 XML_SCHEMAV_INTERNAL,
14330 "Internal error: xmlSchemaAssembleByLocation, "
14331 "failed to create a temp. parser context.\n",
14332 NULL, NULL);
14333 return (-1);
14334 }
14335 pctxt = vctxt->pctxt;
14336 /*
14337 * Set the counter to produce unique names for anonymous items.
14338 */
14339 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014340 /*
14341 * Acquire the schema document.
14342 */
14343 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14344 nsName, location, &doc, &targetNs, 0);
14345 if (ret != 0) {
14346 if (doc != NULL)
14347 xmlFreeDoc(doc);
14348 } else if (doc != NULL) {
14349 docElem = xmlDocGetRootElement(doc);
14350 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014351 * Create new assemble info.
14352 */
14353 if (pctxt->assemble == NULL) {
14354 pctxt->assemble = xmlSchemaNewAssemble();
14355 if (pctxt->assemble == NULL) {
14356 xmlSchemaVErrMemory(vctxt,
14357 "Memory error: xmlSchemaAssembleByLocation, "
14358 "allocating assemble info", NULL);
14359 xmlFreeDoc(doc);
14360 return (-1);
14361 }
14362 }
14363 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014364 * Save and reset the context & schema.
14365 */
14366 oldflags = schema->flags;
14367 oldtns = schema->targetNamespace;
14368 olddoc = schema->doc;
14369
14370 xmlSchemaClearSchemaDefaults(schema);
14371 schema->targetNamespace = targetNs;
14372 /* schema->nbCurItems = 0; */
14373 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014374 pctxt->ctxtType = NULL;
14375 pctxt->parentItem = NULL;
14376
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014377 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14378 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014379 xmlSchemaPostSchemaAssembleFixup(pctxt);
14380 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014381 * Set the counter of items.
14382 */
14383 schema->counter = pctxt->counter;
14384 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014385 * Free the list of assembled components.
14386 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014387 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014388 /*
14389 * Restore the context & schema.
14390 */
14391 schema->flags = oldflags;
14392 schema->targetNamespace = oldtns;
14393 schema->doc = olddoc;
14394 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014395 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014396 return (ret);
14397}
14398
14399/**
14400 * xmlSchemaAssembleByXSIAttr:
14401 * @vctxt: a schema validation context
14402 * @xsiAttr: an xsi attribute
14403 * @noNamespace: whether a schema with no target namespace is exptected
14404 *
14405 * Expands an existing schema by an additional schema using
14406 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14407 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14408 * must be set to 1.
14409 *
14410 * Returns 0 if the new schema is correct, a positive error code
14411 * number otherwise and -1 in case of an internal or API error.
14412 */
14413static int
14414xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14415 xmlAttrPtr xsiAttr,
14416 int noNamespace)
14417{
14418 xmlChar *value;
14419 const xmlChar *cur, *end;
14420 const xmlChar *nsname = NULL, *location;
14421 int count = 0;
14422 int ret = 0;
14423
14424 if (xsiAttr == NULL) {
14425 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14426 NULL, NULL,
14427 "Internal error: xmlSchemaAssembleByXSIAttr, "
14428 "bad arguments", NULL);
14429 return (-1);
14430 }
14431 /*
14432 * Parse the value; we will assume an even number of values
14433 * to be given (this is how Xerces and XSV work).
14434 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014435 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014436 cur = value;
14437 do {
14438 if (noNamespace != 1) {
14439 /*
14440 * Get the namespace name.
14441 */
14442 while (IS_BLANK_CH(*cur))
14443 cur++;
14444 end = cur;
14445 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14446 end++;
14447 if (end == cur)
14448 break;
14449 count++;
14450 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14451 cur = end;
14452 }
14453 /*
14454 * Get the URI.
14455 */
14456 while (IS_BLANK_CH(*cur))
14457 cur++;
14458 end = cur;
14459 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14460 end++;
14461 if (end == cur)
14462 break;
14463 count++;
14464 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014465 cur = end;
14466 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014467 xsiAttr->parent, nsname, location);
14468 if (ret == -1) {
14469 xmlSchemaVCustomErr(vctxt,
14470 XML_SCHEMAV_INTERNAL,
14471 (xmlNodePtr) xsiAttr, NULL,
14472 "Internal error: xmlSchemaAssembleByXSIAttr, "
14473 "assembling schemata", NULL);
14474 if (value != NULL)
14475 xmlFree(value);
14476 return (-1);
14477 }
14478 } while (*cur != 0);
14479 if (value != NULL)
14480 xmlFree(value);
14481 return (ret);
14482}
14483
14484/**
14485 * xmlSchemaAssembleByXSIElem:
14486 * @vctxt: a schema validation context
14487 * @elem: an element node possibly holding xsi attributes
14488 * @noNamespace: whether a schema with no target namespace is exptected
14489 *
14490 * Assembles an existing schema by an additional schema using
14491 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14492 * of the given @elem.
14493 *
14494 * Returns 0 if the new schema is correct, a positive error code
14495 * number otherwise and -1 in case of an internal or API error.
14496 */
14497static int
14498xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14499 xmlNodePtr elem)
14500{
14501 int ret = 0, retNs = 0;
14502 xmlAttrPtr attr;
14503
14504 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14505 if (attr != NULL) {
14506 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14507 if (retNs == -1)
14508 return (-1);
14509 }
14510 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14511 if (attr != NULL) {
14512 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14513 if (ret == -1)
14514 return (-1);
14515 }
14516 if (retNs != 0)
14517 return (retNs);
14518 else
14519 return (ret);
14520}
14521
Daniel Veillard4255d502002-04-16 15:50:10 +000014522/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014523 * xmlSchemaValidateCallback:
14524 * @ctxt: a schema validation context
14525 * @name: the name of the element detected (might be NULL)
14526 * @type: the type
14527 *
14528 * A transition has been made in the automata associated to an element
14529 * content model
14530 */
14531static void
14532xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014533 const xmlChar * name ATTRIBUTE_UNUSED,
14534 xmlSchemaTypePtr type, xmlNodePtr node)
14535{
Daniel Veillard4255d502002-04-16 15:50:10 +000014536 xmlSchemaTypePtr oldtype = ctxt->type;
14537 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014538
Daniel Veillard4255d502002-04-16 15:50:10 +000014539#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014540 xmlGenericError(xmlGenericErrorContext,
14541 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014542 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014543#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014544 /*
14545 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14546 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014547 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014548 ctxt->node = node;
14549 ctxt->cur = node->children;
14550 /*
14551 * Assemble new schemata using xsi.
14552 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014553 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014554 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014555
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014556 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14557 if (ret == -1) {
14558 xmlSchemaVCustomErr(ctxt,
14559 XML_SCHEMAV_INTERNAL,
14560 ctxt->node, NULL,
14561 "Internal error: xmlSchemaValidateElement, "
14562 "assembling schema by xsi", NULL);
14563 return;
14564 }
14565 /*
14566 * NOTE: We won't react on schema parser errors here.
14567 * TODO: But a warning would be nice.
14568 */
14569 }
14570 switch (type->type) {
14571 case XML_SCHEMA_TYPE_ELEMENT: {
14572 /*
14573 * NOTE: The build of the content model
14574 * (xmlSchemaBuildAContentModel) ensures that the element
14575 * declaration (and not a reference to it) will be given.
14576 */
14577 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14578 /*
14579 * This is paranoid coding ;-)... it should not
14580 * happen here any more.
14581 */
14582 xmlSchemaVCustomErr(ctxt,
14583 XML_SCHEMAV_INTERNAL,
14584 node, NULL,
14585 "Internal error: xmlSchemaValidateCallback, "
14586 "element declaration 'reference' encountered, "
14587 "but an element declaration was expected",
14588 NULL);
14589 return;
14590 }
14591 xmlSchemaValidateElementByDeclaration(ctxt,
14592 (xmlSchemaElementPtr) type);
14593 break;
14594 }
14595 case XML_SCHEMA_TYPE_ANY:
14596 xmlSchemaValidateElementByWildcard(ctxt, type);
14597 break;
14598 default:
14599 break;
14600 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014601 ctxt->type = oldtype;
14602 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014603}
Daniel Veillard4255d502002-04-16 15:50:10 +000014604
Daniel Veillard01fa6152004-06-29 17:04:39 +000014605/**
14606 * xmlSchemaValidateSimpleTypeValue:
14607 * @ctxt: a schema validation context
14608 * @value: the value to be validated
14609 * @fireErrors: shall errors be reported?
14610 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014611 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014612 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014613 *
14614 * Validates a value by the given type (user derived or built-in).
14615 *
14616 * Returns 0 if the value is valid, a positive error code
14617 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014618 */
14619static int
14620xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014621 xmlSchemaTypePtr type,
14622 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014623 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014624 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014625 int normalize,
14626 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014627{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014628 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014629 int ret = 0;
14630 xmlChar *normValue = NULL;
14631 int wtsp;
14632
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014633 node = ctxt->node;
14634 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014635 wtsp = ctxt->valueWS;
14636 /*
14637 * Normalize the value.
14638 */
14639 if (normalize &&
14640 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14641 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14642
14643 if ((norm != -1) && (norm > ctxt->valueWS)) {
14644 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14645 normValue = xmlSchemaCollapseString(value);
14646 else
14647 normValue = xmlSchemaWhiteSpaceReplace(value);
14648 ctxt->valueWS = norm;
14649 if (normValue != NULL)
14650 value = (const xmlChar *) normValue;
14651 }
14652 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014653 /*
14654 * The nodes of a content must be checked only once,
14655 * this is not working since list types will fire this
14656 * multiple times.
14657 */
14658 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14659 xmlNodePtr cur = ctxt->cur;
14660
14661 do {
14662 switch (cur->type) {
14663 case XML_TEXT_NODE:
14664 case XML_CDATA_SECTION_NODE:
14665 case XML_PI_NODE:
14666 case XML_COMMENT_NODE:
14667 case XML_XINCLUDE_START:
14668 case XML_XINCLUDE_END:
14669 break;
14670 case XML_ENTITY_REF_NODE:
14671 case XML_ENTITY_NODE:
14672 /* TODO: Scour the entities for illegal nodes. */
14673 TODO break;
14674 case XML_ELEMENT_NODE: {
14675 /* NOTE: Changed to an internal error, since the
14676 * existence of an element node will be already checked in
14677 * xmlSchemaValidateElementBySimpleType and in
14678 * xmlSchemaValidateElementByComplexType.
14679 */
14680 xmlSchemaVCustomErr(ctxt,
14681 XML_SCHEMAV_INTERNAL,
14682 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14683 node, type,
14684 "Element '%s' found in simple type content",
14685 cur->name);
14686 return (XML_SCHEMAV_INTERNAL);
14687 }
14688 case XML_ATTRIBUTE_NODE:
14689 case XML_DOCUMENT_NODE:
14690 case XML_DOCUMENT_TYPE_NODE:
14691 case XML_DOCUMENT_FRAG_NODE:
14692 case XML_NOTATION_NODE:
14693 case XML_HTML_DOCUMENT_NODE:
14694 case XML_DTD_NODE:
14695 case XML_ELEMENT_DECL:
14696 case XML_ATTRIBUTE_DECL:
14697 case XML_ENTITY_DECL:
14698 case XML_NAMESPACE_DECL:
14699#ifdef LIBXML_DOCB_ENABLED
14700 case XML_DOCB_DOCUMENT_NODE:
14701#endif
14702 xmlSchemaVCustomErr(ctxt,
14703 XML_SCHEMAV_INTERNAL,
14704 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14705 node, NULL,
14706 "Node of unexpected type found in simple type content",
14707 NULL);
14708 return (XML_SCHEMAV_INTERNAL);
14709 }
14710 cur = cur->next;
14711 } while (cur != NULL);
14712 }
14713
William M. Brack2f2a6632004-08-20 23:09:47 +000014714 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14715 xmlSchemaTypePtr base, anyType;
14716
14717 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14718
14719 base = type->baseType;
14720 while ((base != NULL) &&
14721 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14722 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14723 (base != anyType)) {
14724 base = base->baseType;
14725 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014726 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014727 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014728 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014729 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14730 "validating complex type '%s'\n",
14731 type->name, NULL);
14732 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14733 /*
14734 * Check facets.
14735 */
14736 /*
14737 * This is somehow not nice, since if an error occurs
14738 * the reported type will be the complex type; the spec
14739 * wants a simple type to be created on the complex type
14740 * if it has a simple content. For now we have to live with
14741 * it.
14742 */
14743 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14744 value, 0, fireErrors);
14745 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014746 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014747 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14748 "validating facets of complex type '%s'\n",
14749 type->name, NULL);
14750 } else if (ret > 0) {
14751 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014752 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014753 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014754 }
14755 }
14756 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014757
14758 if (ctxt->value != NULL) {
14759 xmlSchemaFreeValue(ctxt->value);
14760 ctxt->value = NULL;
14761 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014762 /*
14763 * STREAM-READ-CHILDREN.
14764 */
14765 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014766 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014767 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14768 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14769 else
14770 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014771 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014772 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014773 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014774 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014775 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014776 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014777 }
14778 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14779 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14780 * a literal in the ·lexical space· of {base type definition}
14781 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014782 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014783 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014784 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014785 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014786 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014787 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014788 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014789 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014790 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014791 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014792 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014793 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014794 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014795 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014796 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14797 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014798 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014799 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014800 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014801 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014802 type->name, NULL);
14803 } else if (ret > 0) {
14804 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014805 /*
14806 Disabled, since the facet validation already reports errors.
14807 if (fireErrors)
14808 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14809 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014810 }
14811 }
14812 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14813
14814 xmlSchemaTypePtr tmpType;
14815 const xmlChar *cur, *end;
14816 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014817 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014818
14819 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14820 * of white space separated tokens, each of which ·match·es a literal
14821 * in the ·lexical space· of {item type definition}
14822 */
14823
Daniel Veillardc0826a72004-08-10 14:17:33 +000014824 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014825 cur = value;
14826 do {
14827 while (IS_BLANK_CH(*cur))
14828 cur++;
14829 end = cur;
14830 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14831 end++;
14832 if (end == cur)
14833 break;
14834 tmp = xmlStrndup(cur, end - cur);
14835 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014836 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014837 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014838 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014839 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014840 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14841 "validating an item of list simple type '%s'\n",
14842 type->name, NULL);
14843 break;
14844 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014845 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014846 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014847 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014848 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014849 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014850 cur = end;
14851 } while (*cur != 0);
14852 /*
14853 * Check facets.
14854 */
14855 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014856 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014857 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014858 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014859 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014860 } else if ((ret == 0) && (applyFacets)) {
14861 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14862 value, len, fireErrors);
14863 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014864 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014865 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14866 "validating facets of list simple type '%s'\n",
14867 type->name, NULL);
14868 } else if (ret > 0) {
14869 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014870 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014871 Disabled, since the facet validation already reports errors.
14872 if (fireErrors)
14873 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014874 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014875 }
14876
Daniel Veillard01fa6152004-06-29 17:04:39 +000014877 }
14878 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14879 xmlSchemaTypeLinkPtr memberLink;
14880
14881 /*
14882 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14883 * not apply directly; however, the normalization behavior of ·union·
14884 * types is controlled by the value of whiteSpace on that one of the
14885 * ·memberTypes· against which the ·union· is successfully validated.
14886 *
14887 * This means that the value is normalized by the first validating
14888 * member type, then the facets of the union type are applied. This
14889 * needs changing of the value!
14890 */
14891
14892 /*
14893 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14894 * literal in the ·lexical space· of at least one member of
14895 * {member type definitions}
14896 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014897#ifdef DEBUG_UNION_VALIDATION
14898 printf("Union ST : '%s'\n", (const char *) type->name);
14899 printf(" fireErrors : %d\n", fireErrors);
14900 printf(" applyFacets: %d\n", applyFacets);
14901#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014902 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14903 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014904 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014905 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014906 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014907 type->name, NULL);
14908 ret = -1;
14909 }
14910 if (ret == 0) {
14911 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014912 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14913 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014914 if ((ret <= 0) || (ret == 0))
14915 break;
14916 memberLink = memberLink->next;
14917 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014918 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014919 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014920 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014921 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014922 type->name, NULL);
14923 } else if (ret > 0) {
14924 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014925 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014926 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014927 }
14928 }
14929 /*
14930 * Apply facets (pattern, enumeration).
14931 */
14932 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14933 int mws;
14934 /*
14935 * The normalization behavior of ·union· types is controlled by
14936 * the value of whiteSpace on that one of the ·memberTypes·
14937 * against which the ·union· is successfully validated.
14938 */
14939 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014940 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014941 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14942 "the value was already normalized for the union simple "
14943 "type '%s'.\n", type->name, NULL);
14944 }
14945 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14946 if (mws > ctxt->valueWS) {
14947 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14948 normValue = xmlSchemaCollapseString(value);
14949 else
14950 normValue = xmlSchemaWhiteSpaceReplace(value);
14951 if (normValue != NULL)
14952 value = (const xmlChar *) normValue;
14953 }
14954
14955 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14956 value, 0, fireErrors);
14957 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014958 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014959 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14960 "validating facets of union simple type '%s'\n",
14961 type->name, NULL);
14962 } else if (ret > 0) {
14963 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14964 /*
14965 if (fireErrors)
14966 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14967 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014968 }
14969 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014970 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014971 ctxt->valueWS = wtsp;
14972 if (normValue != NULL)
14973 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014974 return (ret);
14975}
14976
14977/**
14978 * xmlSchemaValidateSimpleTypeElement:
14979 * @ctxt: a schema validation context
14980 * @node: the element node to be validated.
14981 *
14982 * Validate the element against a simple type.
14983 *
14984 * Returns 0 if the element is valid, a positive error code
14985 * number otherwise and -1 in case of an internal or API error.
14986 */
14987static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014988xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014989 xmlSchemaTypePtr type,
14990 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014991{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014992 xmlSchemaTypePtr oldtype;
14993 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014994 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014995 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014996 int ret = 0, retval = 0;
14997
Daniel Veillard01fa6152004-06-29 17:04:39 +000014998 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014999 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
15000 "Internal error: xmlSchemaValidateElementBySimpleType, "
15001 "bad arguments", NULL);
15002 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015003 }
15004
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015005 oldtype = ctxt->type;
15006 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015007 /*
15008 * cvc-type: 3.1.2 The element information item must have no element
15009 * information item [children].
15010 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015011 /*
15012 * STREAM: Child nodes are processed.
15013 */
15014 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015015 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015016 /*
15017 * TODO: Entities, will they produce elements as well?
15018 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015019 if (cur->type == XML_ELEMENT_NODE) {
15020 xmlSchemaVCustomErr(ctxt,
15021 XML_SCHEMAV_CVC_TYPE_3_1_2,
15022 node, type,
15023 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015024 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015025 }
15026 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015027 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015028
Daniel Veillard01fa6152004-06-29 17:04:39 +000015029 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015030 * cvc-type 3.1.1:
15031 *
15032 * The attributes of must be empty, excepting those whose namespace name
15033 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
15034 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015035 */
15036 /*
15037 * STREAM: Attribute nodes are processed.
15038 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015039 attr = node->properties;
15040 while (attr != NULL) {
15041 if ((attr->ns == NULL) ||
15042 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
15043 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
15044 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
15045 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
15046 (!xmlStrEqual
15047 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015048 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015049 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
15050 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015051 }
15052 attr = attr->next;
15053 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015054 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015055 * This will skip validation if the type is 'anySimpleType' and
15056 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015057 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015058 if ((valSimpleContent == 1) &&
15059 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
15060 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015061 xmlChar *value;
15062
15063 value = xmlNodeGetContent(node);
15064 /*
15065 * NOTE: This call will not check the content nodes, since
15066 * this should be checked here already.
15067 */
15068 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
15069 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015070 if (value != NULL)
15071 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015072 if (retval != 0)
15073 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000015074 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015075 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015076 return (ret);
15077}
Daniel Veillard4255d502002-04-16 15:50:10 +000015078
15079/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015080 * xmlSchemaValQNameAcquire:
15081 * @value: the lexical represantation of the QName value
15082 * @node: the node to search for the corresponding namespace declaration
15083 * @nsName: the resulting namespace name if found
15084 *
15085 * Checks that a value conforms to the lexical space of the type QName;
15086 * if valid, the corresponding namespace name is searched and retured
15087 * as a copy in @nsName. The local name is returned in @localName as
15088 * a copy.
15089 *
15090 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
15091 * namespace declaration was found in scope; -1 in case of an internal or
15092 * API error.
15093 */
15094static int
15095xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
15096 xmlChar **nsName, xmlChar **localName)
15097{
15098 int ret;
15099 xmlChar *local = NULL;
15100
15101 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
15102 return (-1);
15103 *nsName = NULL;
15104 *localName = NULL;
15105 ret = xmlValidateQName(value, 1);
15106 if (ret == 0) {
15107 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015108 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015109
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015110 /*
15111 * NOTE: xmlSplitQName2 will return a duplicated
15112 * string.
15113 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015114 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015115 if (local == NULL)
15116 local = xmlStrdup(value);
15117 ns = xmlSearchNs(node->doc, node, prefix);
15118 /*
15119 * A namespace need not to be found if the prefix is NULL.
15120 */
15121 if (ns != NULL) {
15122 /*
15123 * TODO: Is it necessary to duplicate the URI here?
15124 */
15125 *nsName = xmlStrdup(ns->href);
15126 } else if (prefix != NULL) {
15127 xmlFree(prefix);
15128 if (local != NULL)
15129 xmlFree(local);
15130 return (2);
15131 }
15132 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015133 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015134 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015135 } else
15136 return (1);
15137 return (ret);
15138}
15139
15140/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015141 * xmlSchemaHasElemContent:
15142 * @node: the node
15143 *
15144 * Scours the content of the given node for element
15145 * nodes.
15146 *
15147 * Returns 1 if an element node is found,
15148 * 0 otherwise.
15149 */
15150static int
15151xmlSchemaHasElemContent(xmlNodePtr node)
15152{
15153 if (node == NULL)
15154 return (0);
15155 node = node->children;
15156 while (node != NULL) {
15157 if (node->type == XML_ELEMENT_NODE)
15158 return (1);
15159 node = node->next;
15160 }
15161 return (0);
15162}
15163/**
15164 * xmlSchemaHasElemOrCharContent:
15165 * @node: the node
15166 *
15167 * Scours the content of the given node for element
15168 * and character nodes.
15169 *
15170 * Returns 1 if an element or character node is found,
15171 * 0 otherwise.
15172 */
15173static int
15174xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15175{
15176 if (node == NULL)
15177 return (0);
15178 node = node->children;
15179 while (node != NULL) {
15180 switch (node->type) {
15181 case XML_ELEMENT_NODE:
15182 /*
15183 * TODO: Ask Daniel if these are all character nodes.
15184 */
15185 case XML_TEXT_NODE:
15186 case XML_CDATA_SECTION_NODE:
15187 /*
15188 * TODO: How XML_ENTITY_NODEs evaluated?
15189 */
15190 case XML_ENTITY_REF_NODE:
15191 case XML_ENTITY_NODE:
15192 return (1);
15193 break;
15194 default:
15195 break;
15196 }
15197 node = node->next;
15198 }
15199 return (0);
15200}
15201
15202
15203/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015204 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015205 * @ctxt: a schema validation context
15206 * @node: the top node.
15207 *
15208 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015209 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015210 *
15211 * Returns 0 if the element is schemas valid, a positive error code
15212 * number otherwise and -1 in case of internal or API error.
15213 */
15214static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015215xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15216 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015217{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015218 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015219 int ret = 0;
15220 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015221 xmlAttrPtr attr;
15222 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015223 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015224
15225 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015226 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15227 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015228 * Note that @elemDecl will be the declaration and never the
15229 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015230 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015231
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015232 if (ctxt == NULL) {
15233 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15234 "Internal error: xmlSchemaValidateElementByDeclaration, "
15235 "bad arguments.\n",
15236 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015237 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015238 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015239
15240 elem = ctxt->node;
15241
15242 /*
15243 * cvc-elt (3.3.4) : 1
15244 */
15245 if (elemDecl == NULL) {
15246 xmlSchemaVCustomErr(ctxt,
15247 XML_SCHEMAV_CVC_ELT_1,
15248 elem, NULL,
15249 "No matching declaration available", NULL);
15250 return (ctxt->err);
15251 }
15252 /*
15253 * cvc-elt (3.3.4) : 2
15254 */
15255 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15256 xmlSchemaVCustomErr(ctxt,
15257 XML_SCHEMAV_CVC_ELT_2,
15258 elem, NULL,
15259 "The element declaration is abstract", NULL);
15260 return (ctxt->err);
15261 }
15262
15263 /*
15264 * cvc-elt (3.3.4) : 3
15265 * Handle 'xsi:nil'.
15266 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015267
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015268 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015269 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015270 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15271 ctxt->node = (xmlNodePtr) attr;
15272 ctxt->cur = attr->children;
15273 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15274 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15275 BAD_CAST attrValue, 1, 1, 1, 1);
15276 ctxt->node = elem;
15277 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15278 if (ret < 0) {
15279 xmlSchemaVCustomErr(ctxt,
15280 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015281 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015282 "Internal error: xmlSchemaValidateElementByDeclaration, "
15283 "validating the attribute 'xsi:nil'", NULL);
15284 if (attrValue != NULL)
15285 xmlFree(attrValue);
15286 return (-1);
15287 }
15288 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015289 /*
15290 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015291 */
15292 xmlSchemaVCustomErr(ctxt,
15293 XML_SCHEMAV_CVC_ELT_3_1,
15294 elem, NULL,
15295 "The element is not 'nillable'", NULL);
15296 } else {
15297 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015298 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015299 ret = 0;
15300 /*
15301 * cvc-elt (3.3.4) : 3.2.1
15302 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015303 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15304 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015305 xmlSchemaVCustomErr(ctxt,
15306 XML_SCHEMAV_CVC_ELT_3_2_1,
15307 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015308 elem, (xmlSchemaTypePtr) elemDecl,
15309 "The 'nilled' element must have no character or "
15310 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015311 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15312 }
15313 /*
15314 * cvc-elt (3.3.4) : 3.2.2
15315 */
15316 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15317 (elemDecl->value != NULL)) {
15318 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15319 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015320 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015321 "There is a fixed value constraint defined for "
15322 "the 'nilled' element", NULL);
15323 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15324 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015325 if (ret == 0)
15326 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015327 }
15328 }
15329 if (attrValue != NULL)
15330 xmlFree(attrValue);
15331 }
15332
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015333
15334 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015335 /*
15336 * cvc-elt (3.3.4) : 4
15337 * Handle 'xsi:type'.
15338 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015339
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015340 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15341 if (attr != NULL) {
15342 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015343
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015344 /*
15345 * TODO: We should report a *warning* that the type was overriden
15346 * by the instance.
15347 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015348
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015349 /*
15350 * cvc-elt (3.3.4) : 4.1
15351 */
15352 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15353 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15354 &nsName, &local);
15355 if (ret < 0) {
15356 xmlSchemaVCustomErr(ctxt,
15357 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015358 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015359 "Internal error: xmlSchemaValidateElementByDeclaration, "
15360 "validating the attribute 'xsi:type'", NULL);;
15361 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015362 FREE_AND_NULL(nsName)
15363 FREE_AND_NULL(local)
15364 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015365 } else if (ret == 1) {
15366 xmlSchemaVSimpleTypeErr(ctxt,
15367 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15368 (xmlNodePtr) attr, attrValue,
15369 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15370 } else if (ret == 2) {
15371 xmlSchemaVCustomErr(ctxt,
15372 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15373 (xmlNodePtr) attr,
15374 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15375 "The QName value '%s' has no "
15376 "corresponding namespace declaration in scope",
15377 attrValue);
15378 } else {
15379 /*
15380 * cvc-elt (3.3.4) : 4.2
15381 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015382 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15383 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015384 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015385
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015386 xmlSchemaVCustomErr(ctxt,
15387 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015388 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015389 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15390 "The value %s does not resolve to a type "
15391 "definition",
15392 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15393 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015394 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015395 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015396 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015397 */
15398 }
15399 }
15400 FREE_AND_NULL(attrValue)
15401 FREE_AND_NULL(nsName)
15402 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015403 }
15404 /* TODO: Change the handling of missing types according to
15405 * the spec.
15406 */
15407 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015408 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015409 XML_SCHEMAV_CVC_TYPE_1,
15410 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015411 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015412 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015413 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015414
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015415 /*
15416 * TODO: Since this should be already checked by the content model automaton,
15417 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15418 * has been changed to XML_SCHEMAV_INTERNAL.
15419 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015420 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015421 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015422 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015423 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015424 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015425 "Element %s: missing child %s\n",
15426 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015427 }
15428 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015429 }
15430 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015431 /*
15432 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015433 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015434 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015435 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015436 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015437 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015438 "Element %s: missing child %s found %s\n",
15439 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015440 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015441 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015442 */
15443 if (elemHasContent == -1)
15444 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15445 /*
15446 * cvc-elt (3.3.4) : 5
15447 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015448 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015449 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015450 * cvc-elt (3.3.4) : 5.1
15451 * If the declaration has a {value constraint},
15452 * the item has neither element nor character [children] and
15453 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015454 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015455 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15456 /*
15457 * cvc-elt (3.3.4) : 5.1.1
15458 * If the ·actual type definition· is a ·local type definition·
15459 * then the canonical lexical representation of the {value constraint}
15460 * value must be a valid default for the ·actual type definition· as
15461 * defined in Element Default Valid (Immediate) (§3.3.6).
15462 */
15463 /*
15464 * NOTE: 'local' above means types aquired by xsi:type.
15465 */
15466 ret = 0;
15467 if (actualType != elemDecl->subtypes) {
15468 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15469 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15470 elemDecl->value, NULL);
15471 if (ret < 0) {
15472 xmlSchemaVCustomErr(ctxt,
15473 XML_SCHEMAV_INTERNAL,
15474 elem, actualType,
15475 "Internal error: xmlSchemaValidateElementByDeclaration, "
15476 "validating a default value", NULL);
15477 return (-1);
15478 }
15479 }
15480 /*
15481 * cvc-elt (3.3.4) : 5.1.2
15482 * The element information item with the canonical lexical
15483 * representation of the {value constraint} value used as its
15484 * ·normalized value· must be ·valid· with respect to the
15485 * ·actual type definition· as defined by Element Locally Valid (Type)
15486 * (§3.3.4).
15487 */
15488 /*
15489 * Disable validation of the simple content, since it was already
15490 * done above.
15491 */
15492 if (ret == 0) {
15493 if (actualType != elemDecl->subtypes)
15494 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15495 else
15496 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15497 ctxt->node = elem;
15498 if (ret < 0) {
15499 xmlSchemaVCustomErr(ctxt,
15500 XML_SCHEMAV_INTERNAL,
15501 elem, actualType,
15502 "Internal error: xmlSchemaValidateElementByDeclaration, "
15503 "validating against the type", NULL);
15504 return (-1);
15505 }
15506 /*
15507 * PSVI: Create a text node on the instance element.
15508 */
15509 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15510 xmlNodePtr textChild;
15511
15512 textChild = xmlNewText(elemDecl->value);
15513 if (textChild == NULL) {
15514 xmlSchemaVCustomErr(ctxt,
15515 XML_SCHEMAV_INTERNAL,
15516 elem, actualType,
15517 "Internal error: xmlSchemaValidateElementByDeclaration, "
15518 "could not create a default text node for the instance",
15519 NULL);
15520 } else
15521 xmlAddChild(elem, textChild);
15522 }
15523 }
15524
15525 } else {
15526 /*
15527 * 5.2.1 The element information item must be ·valid· with respect
15528 * to the ·actual type definition· as defined by Element Locally
15529 * Valid (Type) (§3.3.4).
15530 */
15531 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15532 ctxt->node = elem;
15533 if (ret < 0) {
15534 xmlSchemaVCustomErr(ctxt,
15535 XML_SCHEMAV_INTERNAL,
15536 elem, actualType,
15537 "Internal error: xmlSchemaValidateElementByDeclaration, "
15538 "validating a default value", NULL);
15539 return (-1);
15540 }
15541 /*
15542 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15543 * not applied, all of the following must be true:
15544 */
15545
15546 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15547 /*
15548 * 5.2.2.1 The element information item must have no element
15549 * information item [children].
15550 *
15551 * TODO REDUNDANT: If the actual type exists, the above call to
15552 * xmlSchemaValidateElementByType will already check for element
15553 * nodes.
15554 */
15555 if (xmlSchemaHasElemContent(elem)) {
15556 xmlSchemaVCustomErr(ctxt,
15557 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15558 elem, (xmlSchemaTypePtr) elemDecl,
15559 "Elements in the content are not allowed if it is "
15560 "constrained by a fixed value", NULL);
15561 } else {
15562 /*
15563 * 5.2.2.2 The appropriate case among the following must
15564 * be true:
15565 */
15566
15567 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15568 xmlChar *value;
15569 /*
15570 * 5.2.2.2.1 If the {content type} of the ·actual type
15571 * definition· is mixed, then the *initial value* of the
15572 * item must match the canonical lexical representation
15573 * of the {value constraint} value.
15574 *
15575 * ... the *initial value* of an element information
15576 * item is the string composed of, in order, the
15577 * [character code] of each character information item in
15578 * the [children] of that element information item.
15579 */
15580 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15581 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15582 /*
15583 * TODO: Report invalid & expected values as well.
15584 * TODO: Implement the cononical stuff.
15585 */
15586 xmlSchemaVCustomErr(ctxt,
15587 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15588 elem, (xmlSchemaTypePtr) elemDecl,
15589 "The value does not match the cononical "
15590 "lexical representation of the fixed constraint",
15591 NULL);
15592 }
15593 if (value != NULL)
15594 xmlFree(value);
15595 } else if ((actualType->contentType ==
15596 XML_SCHEMA_CONTENT_SIMPLE) ||
15597 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15598 xmlChar *value;
15599
15600 /*
15601 * 5.2.2.2.2 If the {content type} of the ·actual type
15602 * definition· is a simple type definition, then the
15603 * *actual value* of the item must match the canonical
15604 * lexical representation of the {value constraint} value.
15605 */
15606 /*
15607 * TODO: *actual value* is the normalized value, impl. this.
15608 * TODO: Report invalid & expected values as well.
15609 * TODO: Implement the cononical stuff.
15610 *
15611 */
15612 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15613 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15614 xmlSchemaVCustomErr(ctxt,
15615 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15616 elem, (xmlSchemaTypePtr) elemDecl,
15617 "The normalized value does not match the cononical "
15618 "lexical representation of the fixed constraint",
15619 NULL);
15620 }
15621 if (value != NULL)
15622 xmlFree(value);
15623
15624 }
15625 /*
15626 * TODO: What if the content type is not 'mixed' or simple?
15627 */
15628
15629 }
15630
15631 }
15632 }
15633
15634 /*
15635 * TODO: 6 The element information item must be ·valid· with respect to each of
15636 * the {identity-constraint definitions} as per Identity-constraint
15637 * Satisfied (§3.11.4).
15638 */
15639
15640 /*
15641 * TODO: 7 If the element information item is the ·validation root·, it must be
15642 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15643 */
15644
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015645 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015646}
15647
Daniel Veillard4255d502002-04-16 15:50:10 +000015648/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015649 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015650 * @ctxt: a schema validation context
15651 * @node: the top node.
15652 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015653 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15654 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015655 *
15656 * Returns 0 if the element is valid, a positive error code
15657 * number otherwise and -1 in case of an internal error.
15658 */
15659static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015660xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15661 xmlSchemaWildcardPtr wild,
15662 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015663{
15664 const xmlChar *uri;
15665 int ret = 0;
15666 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015667
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015668 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015669 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15670 if (ret == -1) {
15671 xmlSchemaVCustomErr(ctxt,
15672 XML_SCHEMAV_INTERNAL,
15673 ctxt->node, NULL,
15674 "Internal error: xmlSchemaValidateElement, "
15675 "assembling schema by xsi", NULL);
15676 return (-1);
15677 }
15678 /*
15679 * NOTE: We won't react on schema parser errors here.
15680 * TODO: But a warning would be nice.
15681 */
15682 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015683 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15684 xmlSchemaElementPtr decl = NULL;
15685
15686 if (node->ns != NULL)
15687 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15688 node->name, node->ns->href, NULL);
15689 else
15690 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15691 if (decl != NULL) {
15692 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015693 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015694 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015695 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015696 "Internal error: xmlSchemaValidateAnyInternal, "
15697 "validating an element in the context of a wildcard.",
15698 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000015699 }
15700 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015701 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15702 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015703 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015704 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015705 return (ctxt->err);
15706 }
15707 }
15708 if (node->children != NULL) {
15709 child = node->children;
15710 do {
15711 if (child->type == XML_ELEMENT_NODE) {
15712 if (child->ns != NULL)
15713 uri = child->ns->href;
15714 else
15715 uri = NULL;
15716 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015717 /* TODO: error code. */
15718 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015719 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015720 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015721 return (ctxt->err);
15722 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015723 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15724 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015725 if (ret != 0)
15726 return (ret);
15727 }
15728 child = child->next;
15729 } while (child != NULL);
15730 }
15731 return (0);
15732}
15733
15734/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015735 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015736 * @ctxt: a schema validation context
15737 *
15738 * Returns 0 if the element is valid, a positive error code
15739 * number otherwise and -1 in case of an internal or API error.
15740 */
15741static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015742xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15743 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015744{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015745 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15746 (ctxt->node == NULL)) {
15747 xmlSchemaVCustomErr(ctxt,
15748 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15749 "Internal error: xmlSchemaValidateElementByWildcard, "
15750 "bad arguments", NULL);
15751 return (-1);
15752 }
15753 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15754 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015755}
15756
15757/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015758 * xmlSchemaValidateAnyTypeContent:
15759 * @ctxt: a schema validation context
15760 * @node: the current element
15761 *
15762 * This one validates the content of an element of the type
15763 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15764 * thus elements in the subtree will be validated, if a corresponding
15765 * declaration in the schema exists.
15766 *
15767 * Returns 0 if the element and its subtree is valid, a positive error code
15768 * otherwise and -1 in case of an internal or API error.
15769 */
15770static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015771xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15772 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015773{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015774 xmlSchemaTypePtr oldtype;
15775 xmlNodePtr top, cur;
15776 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015777 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015778
15779 if ((type == NULL) || (ctxt->node == NULL))
15780 return (-1);
15781
15782 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015783 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015784
15785 oldtype = ctxt->type;
15786 top = ctxt->node;
15787 /*
15788 * STREAM: Child nodes are processed.
15789 */
15790 cur = ctxt->node->children;
15791 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015792 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015793 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015794 /*
15795 * The process contents of the wildcard is "lax", thus
15796 * we need to validate the element if a declaration
15797 * exists.
15798 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015799 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015800 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015801 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015802 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015803 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015804 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015805 ctxt->node = cur;
15806 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15807 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015808 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015809 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015810 "Internal error: xmlSchemaValidateAnyTypeContent, "
15811 "validating an element in the context of a wildcard.",
15812 NULL, NULL);
15813 return (ret);
15814 } else if (ret > 0)
15815 return (ret);
15816 skipContent = 1;
15817 }
15818 }
15819 /*
15820 * Browse the full subtree, deep first.
15821 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015822 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015823 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015824 cur = cur->children;
15825 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015826 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015827 cur = cur->next;
15828 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015829 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015830 while (cur != top) {
15831 if (cur->parent != NULL)
15832 cur = cur->parent;
15833 if ((cur != top) && (cur->next != NULL)) {
15834 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015835 break;
15836 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015837 if (cur->parent == NULL) {
15838 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015839 break;
15840 }
15841 }
15842 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015843 if (cur == top)
15844 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015845 } else
15846 break;
15847 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015848 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015849 return (0);
15850}
15851
15852/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015853 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015854 * @ctxt: a schema validation context
15855 * @node: the top node.
15856 *
15857 * Validate the content of an element expected to be a complex type type
15858 * xmlschema-1.html#cvc-complex-type
15859 * Validation Rule: Element Locally Valid (Complex Type)
15860 *
15861 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015862 * number otherwise and -1 in case of internal or API error.
15863 * Note on reported errors: Although it might be nice to report
15864 * the name of the simple/complex type, used to validate the content
15865 * of a node, it is quite unnecessary: for global defined types
15866 * the local name of the element is equal to the NCName of the type,
15867 * for local defined types it makes no sense to output the internal
15868 * computed name of the type. TODO: Instead, one should attach the
15869 * struct of the type involved to the error handler - this allows
15870 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015871 */
15872static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015873xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015874 xmlSchemaTypePtr type,
15875 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015876{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015877 xmlSchemaTypePtr oldtype;
15878 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015879 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015880 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015881 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015882
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015883 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15884 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015885
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015886 oldtype = ctxt->type;
15887 ctxt->type = type;
15888 elem = ctxt->node;
15889
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015890 /*
15891 * Verify the attributes
15892 */
15893 /*
15894 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015895 */
15896 /* NOTE: removed, since a check for abstract is
15897 * done in the cvc-type constraint.
15898 *
15899 *
15900 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15901 * xmlSchemaVComplexTypeErr(ctxt,
15902 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15903 * elem, type,
15904 * "The type definition is abstract");
15905 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15906 *}
15907 */
15908
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015909 attrs = ctxt->attr;
15910 attrTop = ctxt->attrTop;
15911 /*
15912 * STREAM: Attribute nodes are processed.
15913 */
15914 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15915 xmlSchemaValidateAttributes(ctxt, elem, type);
15916 if (ctxt->attr != NULL)
15917 xmlSchemaFreeAttributeStates(ctxt->attr);
15918 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015919 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015920
15921 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015922 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015923 * model was defined. Somehow ->contModel is always not NULL
15924 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015925 * TODO: Check if the obove still occurs.
15926 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015927 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015928 case XML_SCHEMA_CONTENT_EMPTY: {
15929 /*
15930 * 1 If the {content type} is empty, then the element information
15931 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015932 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015933 /*
15934 * TODO: Is the entity stuff correct?
15935 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015936 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015937 xmlSchemaVComplexTypeErr(ctxt,
15938 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015939 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015940 "Character or element content is not allowed, "
15941 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015942 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015943 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015944 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015945 case XML_SCHEMA_CONTENT_MIXED:
15946 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015947 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015948 /*
15949 * The type has 'anyType' as its base and no content model
15950 * is defined -> use 'anyType' as the type to validate
15951 * against.
15952 */
15953 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15954 /* TODO: Handle -1. */
15955 break;
15956 }
15957 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015958 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015959 {
15960 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000015961 xmlChar *values[10];
15962 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015963
15964 /*
15965 * Content model check initialization.
15966 */
15967 if (type->contModel != NULL) {
15968 oldregexp = ctxt->regexp;
15969 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15970 (xmlRegExecCallbacks)
15971 xmlSchemaValidateCallback, ctxt);
15972#ifdef DEBUG_AUTOMATA
15973 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15974#endif
15975 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015976 /*
15977 * STREAM: Children are processed.
15978 */
15979 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015980 while (child != NULL) {
15981 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015982 if (child->ns != NULL)
15983 nsUri = child->ns->href;
15984 else
15985 nsUri = NULL;
15986 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015987 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015988 /*
15989 * URGENT TODO: Could we anchor an error report
15990 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000015991 * TODO: Perhaps it would be better to report
15992 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015993 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000015994#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000015995 if (ret < 0)
15996 xmlGenericError(xmlGenericErrorContext,
15997 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000015998 else
15999 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016000 " --> %s\n", child->name);
16001#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016002 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016003 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
16004 &values[0], &terminal);
16005 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016006 XML_SCHEMAV_ELEMENT_CONTENT,
16007 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016008 "This element is not expected",
16009 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016010 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016011 /*
16012 * Note that this will skip further validation of the
16013 * content.
16014 */
16015 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016016 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016017 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
16018 /*
16019 * TODO: Ask Daniel if this are all character nodes.
16020 */
16021 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
16022 (child->type == XML_ENTITY_NODE) ||
16023 (child->type == XML_ENTITY_REF_NODE) ||
16024 (child->type == XML_CDATA_SECTION_NODE))) {
16025 /*
16026 * 2.3 If the {content type} is element-only, then the
16027 * element information item has no character information
16028 * item [children] other than those whose [character
16029 * code] is defined as a white space in [XML 1.0 (Second
16030 * Edition)].
16031 */
William M. Brack2f2a6632004-08-20 23:09:47 +000016032 xmlSchemaVComplexTypeErr(ctxt,
16033 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016034 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016035 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016036 "because the content type is element-only");
16037 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016038 break;
16039 }
16040 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016041 }
16042 /*
16043 * Content model check finalization.
16044 */
16045 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016046 if (ret == 0) {
16047 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
16048 &values[0], &terminal);
16049 if (nbval + nbneg != 0) {
16050 /*
16051 * If a next value still exists, I does not have to
16052 * mean that there's an element missing, since it
16053 * might be an optional element. So double check it.
16054 */
16055 ret = xmlRegExecPushString(ctxt->regexp,
16056 NULL, NULL);
16057 if (ret <= 0) {
16058 ret = 1;
16059 xmlSchemaVComplexTypeElemErr(ctxt,
16060 XML_SCHEMAV_ELEMENT_CONTENT,
16061 elem, type, "Missing child element(s)",
16062 nbval, nbneg, values);
16063 } else
16064 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016065#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016066 xmlGenericError(xmlGenericErrorContext,
16067 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016068#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016069 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016070#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016071 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016072 xmlGenericError(xmlGenericErrorContext,
16073 "Element %s content check succeeded\n",
16074 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016075#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016076 }
16077 xmlRegFreeExecCtxt(ctxt->regexp);
16078 ctxt->regexp = oldregexp;
16079 }
16080 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016081 break;
16082 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016083 case XML_SCHEMA_CONTENT_BASIC:
16084 /*
16085 * If the simple content was already validated
16086 * (e.g. a default value), the content need not
16087 * to be validated again.
16088 */
16089 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016090 xmlChar *value = NULL;
16091 /*
16092 * We hit a complexType with a simpleContent resolving
16093 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000016094 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016095 /*
16096 * 2.2 If the {content type} is a simple type definition,
16097 * then the element information item has no element
16098 * information item [children], and the ·normalized value·
16099 * of the element information item is ·valid· with respect
16100 * to that simple type definition as defined by String
16101 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016102 */
16103 /*
16104 * STREAM: Children are processed.
16105 */
16106 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016107 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016108 /*
16109 * TODO: Could the entity stuff produce elements
16110 * as well?
16111 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016112 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016113 xmlSchemaVComplexTypeErr(ctxt,
16114 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016115 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016116 "Element content is not allowed, because "
16117 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016118 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16119 break;
16120 }
16121 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016122 }
16123 ctxt->node = elem;
16124 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016125 if (ret == 0) {
16126 /*
16127 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000016128 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016129 /*
16130 * STREAM: Children are processed.
16131 */
16132 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016133 value = NULL;
16134 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016135 value = xmlNodeGetContent(elem);
16136 /*
16137 * URGENT TODO: Should facets for the simple type validation be
16138 * disabled, if the derivation of facets for complex types
16139 * is implemented?
16140 */
16141 /*
16142 * NOTE: This call won't check the correct types of the
16143 * content nodes, since this should be done here.
16144 */
16145 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016146 if (ret > 0) {
16147 /*
16148 * NOTE: Although an error will be reported by
16149 * xmlSchemaValidateSimpleTypeValue, the spec wants
16150 * a specific complex type error to be reported
16151 * additionally.
16152 */
16153 xmlSchemaVComplexTypeErr(ctxt,
16154 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016155 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016156 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016157 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16158 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016159 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016160 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016161 "Element '%s': Error while validating character "
16162 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016163 elem->name, type->name);
16164 if (value != NULL)
16165 xmlFree(value);
16166 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016167 return (-1);
16168 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016169 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016170 if (ret == 0) {
16171 /*
16172 * Apply facets of the complexType. Be sure to pass the
16173 * built-in type to xmlSchemaValidateFacetsInternal.
16174 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016175 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000016176 * are used, or if the facets, defined by this complex type,
16177 * are to be used only. This here applies both facet sets.
16178 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016179
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016180 ret = xmlSchemaValidateFacetsInternal(ctxt,
16181 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016182 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016183 xmlSchemaVComplexTypeErr(ctxt,
16184 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016185 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016186 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016187 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16188 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016189 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016190 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016191 "Element '%s': Error while validating character "
16192 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000016193 "apply facets.\n",
16194 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016195 if (value != NULL)
16196 xmlFree(value);
16197 ctxt->type = oldtype;
16198 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016199 }
16200 }
16201 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016202 xmlFree(value);
16203
Daniel Veillard01fa6152004-06-29 17:04:39 +000016204 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016205 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016206 default:
16207 TODO xmlGenericError(xmlGenericErrorContext,
16208 "unimplemented content type %d\n",
16209 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016210 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016211 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016212 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016213}
16214
16215/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016216 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016217 * @ctxt: a schema validation context
16218 * @elem: an element
16219 * @type: the list of type declarations
16220 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016221 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016222 *
16223 * Returns 0 if the element is schemas valid, a positive error code
16224 * number otherwise and -1 in case of internal or API error.
16225 */
16226static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016227xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016228 xmlSchemaTypePtr type,
16229 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016230{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016231 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016232
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016233
16234 if ((ctxt == NULL) || (type == NULL)) {
16235 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16236 "Internal error: xmlSchemaValidateElementByType, "
16237 "bad arguments", NULL);
16238 return (-1);
16239 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016240 /*
16241 * This one is called by "xmlSchemaValidateElementByDeclaration".
16242 * It will forward to the proper validation
16243 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016244 */
16245 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016246 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016247 XML_SCHEMAV_CVC_TYPE_1,
16248 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016249 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016250 return (XML_SCHEMAV_CVC_TYPE_1);
16251 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016252
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016253 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016254 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016255 XML_SCHEMAV_CVC_TYPE_2,
16256 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016257 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016258 return (XML_SCHEMAV_CVC_TYPE_2);
16259 }
16260
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016261 switch (type->type) {
16262 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016263 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16264 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016265 break;
16266 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016267 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16268 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016269 break;
16270 case XML_SCHEMA_TYPE_BASIC:
16271 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16272 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16273 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016274 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16275 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016276 break;
16277 default:
16278 ret = -1;
16279 break;
16280 }
16281 if (ret == -1)
16282 return (-1);
16283 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016284 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016285}
16286
16287
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016288static int
16289xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16290 xmlSchemaAttributePtr decl,
16291 xmlSchemaAttrStatePtr state,
16292 xmlAttrPtr attr)
16293{
16294 xmlChar *value;
16295 const xmlChar *defValue;
16296 xmlSchemaValPtr defVal;
16297 int fixed;
16298 int ret;
16299
16300 if (decl->subtypes == NULL) {
16301 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16302 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16303 }
16304 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16305 ctxt->node = (xmlNodePtr) attr;
16306 ctxt->cur = attr->children;
16307 /*
16308 * NOTE: This call also checks the content nodes for correct type.
16309 */
16310 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16311 value, 1, 1, 1, 1);
16312
16313 /*
16314 * Handle 'fixed' attributes.
16315 */
16316 if (ret > 0) {
16317 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16318 /*
16319 * NOTE: Fixed value constraints will be not
16320 * applied if the value was invalid, because:
16321 * 1. The validation process does not return a precomputed
16322 * value.
16323 * 2. An invalid value implies a violation of a fixed
16324 * value constraint.
16325 */
16326 } else if (ret == 0) {
16327 state->state = XML_SCHEMAS_ATTR_CHECKED;
16328 if (xmlSchemaGetEffectiveValueConstraint(decl,
16329 &fixed, &defValue, &defVal) && (fixed == 1)) {
16330 /*
16331 * cvc-au : Attribute Locally Valid (Use)
16332 * For an attribute information item to be·valid·
16333 * with respect to an attribute use its ·normalized
16334 * value· must match the canonical lexical representation
16335 * of the attribute use's {value constraint} value, if it
16336 * is present and fixed.
16337 */
16338 /*
16339 * NOTE: the validation context holds in ctxt->value the
16340 * precomputed value of the attribute; well for some types,
16341 * fallback to string comparison if no computed value
16342 * exists.
16343 */
16344 if (((ctxt->value != NULL) &&
16345 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16346 ((ctxt->value == NULL) &&
16347 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16348 state->state =
16349 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16350 }
16351 }
16352 }
16353 if (value != NULL) {
16354 xmlFree(value);
16355 }
16356 return (ret);
16357}
16358
Daniel Veillard4255d502002-04-16 15:50:10 +000016359/**
16360 * xmlSchemaValidateAttributes:
16361 * @ctxt: a schema validation context
16362 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016363 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016364 *
16365 * Validate the attributes of an element.
16366 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016367 * 1. Existent, invalid attributes are reported in the form
16368 * "prefix:localName".
16369 * Reason: readability - it is easier to find the actual XML
16370 * representation of the attributes QName.
16371 * 2. Missing attributes are reported in the form
16372 * {"URI", "localName"}.
16373 * This is necessary, since the the prefix need not to be declared
16374 * at all, and thus is not computable.
16375 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016376 * Returns 0 if the element is schemas valid, a positive error code
16377 * number otherwise and -1 in case of internal or API error.
16378 */
16379static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016380xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016381{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016382 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016383 int ret;
16384 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016385 const xmlChar *defValue;
16386 xmlSchemaValPtr defVal;
16387 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016388 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016389 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016390 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016391 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016392 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016393 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016394#ifdef DEBUG_ATTR_VALIDATION
16395 int redundant = 0;
16396#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016397
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016398
Daniel Veillardc0826a72004-08-10 14:17:33 +000016399 /*
16400 * Allow all attributes if the type is anyType.
16401 */
16402 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16403 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016404
16405 oldnode = ctxt->node;
16406 if (type != NULL)
16407 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016408 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016409 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016410 attrDecl = attrUse->attr;
16411#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016412 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016413 printf("attr use - use: %d\n", attrDecl->occurs);
16414#endif
16415 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16416
16417 if (curState->decl == attrUse->attr) {
16418#ifdef DEBUG_ATTR_VALIDATION
16419 redundant = 1;
16420#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016421 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016422 attr = curState->attr;
16423#ifdef DEBUG_ATTR_VALIDATION
16424 printf("attr - name: %s\n", attr->name);
16425 if (attr->ns != NULL)
16426 printf("attr - ns: %s\n", attr->ns->href);
16427 else
16428 printf("attr - ns: none\n");
16429#endif
16430 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016431 if (attr == NULL)
16432 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016433 if (attrDecl->ref != NULL) {
16434 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016435 continue;
16436 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016437 if ((attrDecl->refNs == NULL) ||
16438 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016439 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016440 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016441 continue;
16442 }
16443 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016444 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016445 continue;
16446 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016447 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016448 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016449 if (attr->ns == NULL) {
16450 /*
William M. Bracke7091952004-05-11 15:09:58 +000016451 * accept an unqualified attribute only if the target
16452 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016453 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016454 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016455 /*
16456 * This check was removed, since the target namespace
16457 * was evaluated during parsing and already took
16458 * "attributeFormDefault" into account.
16459 */
16460 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016461 continue;
16462 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016463 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016464 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016465 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016466 attr->ns->href))
16467 continue;
16468 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016469 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016470#ifdef DEBUG_ATTR_VALIDATION
16471 printf("found\n");
16472#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016473 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016474 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016475 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016476 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016477 if (!found) {
16478 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16479 xmlSchemaAttrStatePtr tmp;
16480
Daniel Veillard3646d642004-06-02 19:19:14 +000016481#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016482 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016483#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016484 /*
16485 * Add a new dummy attribute state.
16486 */
16487 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16488 if (tmp == NULL) {
16489 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16490 ctxt->node = oldnode;
16491 return (-1);
16492 }
16493 tmp->attr = NULL;
16494 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16495 tmp->decl = attrDecl;
16496 tmp->next = NULL;
16497
16498 if (reqAttrStates == NULL) {
16499 reqAttrStates = tmp;
16500 reqAttrStatesTop = tmp;
16501 } else {
16502 reqAttrStatesTop->next = tmp;
16503 reqAttrStatesTop = tmp;
16504 }
16505 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16506 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16507 &fixed, &defValue, &defVal))) {
16508 xmlSchemaAttrStatePtr tmp;
16509 /*
16510 * Handle non existent default/fixed attributes.
16511 */
16512 tmp = (xmlSchemaAttrStatePtr)
16513 xmlMalloc(sizeof(xmlSchemaAttrState));
16514 if (tmp == NULL) {
16515 xmlSchemaVErrMemory(ctxt,
16516 "registering schema specified attributes", NULL);
16517 ctxt->node = oldnode;
16518 return (-1);
16519 }
16520 tmp->attr = NULL;
16521 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16522 tmp->decl = attrDecl;
16523 tmp->value = defValue;
16524 tmp->next = NULL;
16525
16526 if (defAttrStates == NULL) {
16527 defAttrStates = tmp;
16528 defAttrStates = tmp;
16529 } else {
16530 defAttrStates->next = tmp;
16531 defAttrStatesTop = tmp;
16532 }
16533 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016534 }
16535 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016536 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016537 /*
16538 * Add required attributes to the attribute states of the context.
16539 */
16540 if (reqAttrStates != NULL) {
16541 if (ctxt->attr == NULL) {
16542 ctxt->attr = reqAttrStates;
16543 } else {
16544 ctxt->attrTop->next = reqAttrStates;
16545 }
16546 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016547 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016548 /*
16549 * Process wildcards.
16550 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016551
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016552 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016553#ifdef DEBUG_ATTR_VALIDATION
16554 xmlSchemaWildcardNsPtr ns;
16555 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016556 if (type->attributeWildcard->processContents ==
16557 XML_SCHEMAS_ANY_LAX)
16558 printf("processContents: lax\n");
16559 else if (type->attributeWildcard->processContents ==
16560 XML_SCHEMAS_ANY_STRICT)
16561 printf("processContents: strict\n");
16562 else
16563 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016564 if (type->attributeWildcard->any)
16565 printf("type: any\n");
16566 else if (type->attributeWildcard->negNsSet != NULL) {
16567 printf("type: negated\n");
16568 if (type->attributeWildcard->negNsSet->value == NULL)
16569 printf("ns: (absent)\n");
16570 else
16571 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16572 } else if (type->attributeWildcard->nsSet != NULL) {
16573 printf("type: set\n");
16574 ns = type->attributeWildcard->nsSet;
16575 while (ns != NULL) {
16576 if (ns->value == NULL)
16577 printf("ns: (absent)\n");
16578 else
16579 printf("ns: %s\n", ns->value);
16580 ns = ns->next;
16581 }
16582 } else
16583 printf("empty\n");
16584
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016585
16586#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016587 curState = ctxt->attr;
16588 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016589 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16590 if (curState->attr->ns != NULL)
16591 nsURI = curState->attr->ns->href;
16592 else
16593 nsURI = NULL;
16594 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16595 nsURI)) {
16596 /*
16597 * Handle processContents.
16598 */
16599 if ((type->attributeWildcard->processContents ==
16600 XML_SCHEMAS_ANY_LAX) ||
16601 (type->attributeWildcard->processContents ==
16602 XML_SCHEMAS_ANY_STRICT)) {
16603
16604 attr = curState->attr;
16605 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016606 attr->name, nsURI);
16607 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016608 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016609 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016610 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016611 } else if (type->attributeWildcard->processContents ==
16612 XML_SCHEMAS_ANY_LAX) {
16613 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16614 }
16615 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016616 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016617 }
16618 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016619 curState = curState->next;
16620 }
16621 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016622
Daniel Veillardc0826a72004-08-10 14:17:33 +000016623 /*
16624 * Report missing and illegal attributes.
16625 */
16626 if (ctxt->attr != NULL) {
16627 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016628 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016629 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16630 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016631 if (curState->decl != NULL) {
16632 if (curState->decl->ref != NULL)
16633 attrDecl = curState->decl->refDecl;
16634 else
16635 attrDecl = curState->decl;
16636 } else
16637 attrDecl = NULL;
16638 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16639 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16640 } else if (curState->state ==
16641 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16642 xmlSchemaVCustomErr(ctxt,
16643 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16644 (xmlNodePtr) attr,
16645 (xmlSchemaTypePtr) attrDecl,
16646 "The type definition is absent",
16647 NULL);
16648 } else if (curState->state ==
16649 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16650 xmlSchemaVCustomErr(ctxt,
16651 XML_SCHEMAV_CVC_AU,
16652 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16653 "The value does not match the fixed value "
16654 "constraint", NULL);
16655 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016656 /* TODO: "prohibited" won't ever be touched here!.
16657 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16658 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016659 /*
16660 * TODO: One might report different error messages
16661 * for the following errors.
16662 */
16663 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016664 xmlSchemaVIllegalAttrErr(ctxt,
16665 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16666 } else {
16667 xmlSchemaVIllegalAttrErr(ctxt,
16668 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16669 }
16670 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016671 }
16672 curState = curState->next;
16673 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016674 }
16675
16676 /*
16677 * Add missing default/fixed attributes.
16678 */
16679 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16680 curState = defAttrStates;
16681 while (curState != NULL) {
16682 attrDecl = curState->decl;
16683 if (attrDecl->ref != NULL)
16684 attrDecl = attrDecl->refDecl;
16685 /*
16686 * PSVI: Add a new attribute node to the current element.
16687 */
16688 if (attrDecl->targetNamespace == NULL) {
16689 xmlNewProp(elem, attrDecl->name, curState->value);
16690 } else {
16691 xmlNsPtr ns;
16692
16693 ns = xmlSearchNsByHref(elem->doc, elem,
16694 attrDecl->targetNamespace);
16695 if (ns == NULL) {
16696 xmlChar prefix[12];
16697 int counter = 1;
16698
16699 attr = curState->attr;
16700 /*
16701 * Create a namespace declaration on the validation
16702 * root node if no namespace declaration is in scope.
16703 */
16704 snprintf((char *) prefix, sizeof(prefix), "p");
16705 /*
16706 * This is somehow not performant, since the ancestor
16707 * axis beyond @elem will be searched as well.
16708 */
16709 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16710 while (ns != NULL) {
16711 if (counter > 1000) {
16712 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16713 XML_SCHEMAV_INTERNAL,
16714 "Internal error: xmlSchemaValidateAttributes, "
16715 "could not compute a ns prefix for "
16716 "default/fixed attribute '%s'.\n",
16717 attrDecl->name, NULL);
16718
16719 break;
16720 }
16721 snprintf((char *) prefix,
16722 sizeof(prefix), "p%d", counter++);
16723 ns = xmlSearchNs(elem->doc, elem,
16724 BAD_CAST prefix);
16725 }
16726 if (ns == NULL) {
16727 ns = xmlNewNs(ctxt->validationRoot,
16728 attrDecl->targetNamespace, BAD_CAST prefix);
16729 xmlNewNsProp(elem, ns, attrDecl->name,
16730 curState->value);
16731 }
16732 } else {
16733 xmlNewNsProp(elem, ns, attrDecl->name,
16734 curState->value);
16735 }
16736 }
16737 curState = curState->next;
16738 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016739 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016740 if (defAttrStates != NULL)
16741 xmlSchemaFreeAttributeStates(defAttrStates);
16742
Daniel Veillard3646d642004-06-02 19:19:14 +000016743#ifdef DEBUG_ATTR_VALIDATION
16744 if (redundant)
16745 xmlGenericError(xmlGenericErrorContext,
16746 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16747 type->name);
16748#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016749 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016750 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016751}
16752
16753/**
16754 * xmlSchemaValidateElement:
16755 * @ctxt: a schema validation context
16756 * @elem: an element
16757 *
16758 * Validate an element in a tree
16759 *
16760 * Returns 0 if the element is schemas valid, a positive error code
16761 * number otherwise and -1 in case of internal or API error.
16762 */
16763static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016764xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016765{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016766 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016767 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016768
Daniel Veillardc0826a72004-08-10 14:17:33 +000016769 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016770 * This one is called by xmlSchemaValidateDocument and
16771 * xmlSchemaValidateOneElement.
16772 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016773 if (ctxt->schema == NULL) {
16774 /*
16775 * No schema was specified at time of creation of the validation
16776 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16777 * of the instance to build a schema.
16778 */
16779 if (ctxt->pctxt == NULL)
16780 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16781 if (ctxt->pctxt == NULL)
16782 return (-1);
16783 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16784 if (ctxt->schema == NULL)
16785 return (-1);
16786 /* TODO: assign user data. */
16787 ctxt->pctxt->error = ctxt->error;
16788 ctxt->pctxt->warning = ctxt->warning;
16789 ctxt->xsiAssemble = 1;
16790 } else
16791 ctxt->xsiAssemble = 0;
16792 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16793 * ctxt->xsiAssemble = 1;
16794 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016795 /*
16796 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016797 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016798 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016799 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16800 if (ret == -1) {
16801 xmlSchemaVCustomErr(ctxt,
16802 XML_SCHEMAV_INTERNAL,
16803 ctxt->node, NULL,
16804 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016805 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016806 }
16807 /*
16808 * NOTE: We won't react on schema parser errors here.
16809 * TODO: But a warning would be nice.
16810 */
16811 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016812 if (ret != -1) {
16813 if (ctxt->node->ns != NULL)
16814 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16815 ctxt->node->ns->href);
16816 else
16817 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16818
16819 if (elemDecl == NULL) {
16820 xmlSchemaVCustomErr(ctxt,
16821 XML_SCHEMAV_CVC_ELT_1,
16822 ctxt->node, NULL,
16823 "No matching global declaration available", NULL);
16824 ret = XML_SCHEMAV_CVC_ELT_1;
16825 } else {
16826 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16827 if (ret < 0) {
16828 xmlSchemaVCustomErr(ctxt,
16829 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16830 "Internal error: xmlSchemaValidateElement, "
16831 "calling validation by declaration", NULL);
16832 }
16833 }
16834 }
16835 /* ctxt->xsiAssemble = 0; */
16836 if (ctxt->xsiAssemble) {
16837 if (ctxt->schema != NULL) {
16838 xmlSchemaFree(ctxt->schema);
16839 ctxt->schema = NULL;
16840 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016841 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016842 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016843}
16844
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016845
Daniel Veillard4255d502002-04-16 15:50:10 +000016846/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016847 * xmlSchemaValidateOneElement:
16848 * @ctxt: a schema validation context
16849 * @elem: an element node
16850 *
16851 * Validate a branch of a tree, starting with the given @elem.
16852 *
16853 * Returns 0 if the element and its subtree is valid, a positive error
16854 * code number otherwise and -1 in case of an internal or API error.
16855 */
16856int
16857xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16858{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016859 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016860 return (-1);
16861
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016862 if (ctxt->schema == NULL) {
16863 xmlSchemaVErr(ctxt, NULL,
16864 XML_SCHEMAV_INTERNAL,
16865 "API error: xmlSchemaValidateOneElement, "
16866 "no schema specified.\n", NULL, NULL);
16867 return (-1);
16868 }
16869
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016870 ctxt->doc = elem->doc;
16871 ctxt->err = 0;
16872 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016873 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016874 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016875 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016876}
16877
16878/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016879 * xmlSchemaValidateDocument:
16880 * @ctxt: a schema validation context
16881 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016882 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016883 *
16884 * Validate a document tree in memory.
16885 *
16886 * Returns 0 if the document is schemas valid, a positive error code
16887 * number otherwise and -1 in case of internal or API error.
16888 */
16889static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016890xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16891{
Daniel Veillard4255d502002-04-16 15:50:10 +000016892 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016893
Daniel Veillard4255d502002-04-16 15:50:10 +000016894 root = xmlDocGetRootElement(doc);
16895 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016896 xmlSchemaVCustomErr(ctxt,
16897 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16898 (xmlNodePtr) doc, NULL,
16899 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016900 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016901 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016902 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016903 /*
16904 * Okay, start the recursive validation
16905 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016906 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016907 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016908 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016909
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016910 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016911}
16912
16913/************************************************************************
16914 * *
16915 * SAX Validation code *
16916 * *
16917 ************************************************************************/
16918
16919/************************************************************************
16920 * *
16921 * Validation interfaces *
16922 * *
16923 ************************************************************************/
16924
16925/**
16926 * xmlSchemaNewValidCtxt:
16927 * @schema: a precompiled XML Schemas
16928 *
16929 * Create an XML Schemas validation context based on the given schema
16930 *
16931 * Returns the validation context or NULL in case of error
16932 */
16933xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016934xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16935{
Daniel Veillard4255d502002-04-16 15:50:10 +000016936 xmlSchemaValidCtxtPtr ret;
16937
16938 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16939 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016940 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016941 return (NULL);
16942 }
16943 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016944 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016945 ret->attrTop = NULL;
16946 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016947 return (ret);
16948}
16949
16950/**
16951 * xmlSchemaFreeValidCtxt:
16952 * @ctxt: the schema validation context
16953 *
16954 * Free the resources associated to the schema validation context
16955 */
16956void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016957xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16958{
Daniel Veillard4255d502002-04-16 15:50:10 +000016959 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016960 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016961 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016962 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016963 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016964 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016965 if (ctxt->pctxt != NULL) {
16966 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16967 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016968 xmlFree(ctxt);
16969}
16970
16971/**
16972 * xmlSchemaSetValidErrors:
16973 * @ctxt: a schema validation context
16974 * @err: the error function
16975 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016976 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016977 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016978 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016979 */
16980void
16981xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016982 xmlSchemaValidityErrorFunc err,
16983 xmlSchemaValidityWarningFunc warn, void *ctx)
16984{
Daniel Veillard4255d502002-04-16 15:50:10 +000016985 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016986 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016987 ctxt->error = err;
16988 ctxt->warning = warn;
16989 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016990 if (ctxt->pctxt != NULL)
16991 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000016992}
16993
16994/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016995 * xmlSchemaGetValidErrors:
16996 * @ctxt: a XML-Schema validation context
16997 * @err: the error function result
16998 * @warn: the warning function result
16999 * @ctx: the functions context result
17000 *
17001 * Get the error and warning callback informations
17002 *
17003 * Returns -1 in case of error and 0 otherwise
17004 */
17005int
17006xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
17007 xmlSchemaValidityErrorFunc * err,
17008 xmlSchemaValidityWarningFunc * warn, void **ctx)
17009{
17010 if (ctxt == NULL)
17011 return (-1);
17012 if (err != NULL)
17013 *err = ctxt->error;
17014 if (warn != NULL)
17015 *warn = ctxt->warning;
17016 if (ctx != NULL)
17017 *ctx = ctxt->userData;
17018 return (0);
17019}
17020
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017021
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017022/**
Daniel Veillard6927b102004-10-27 17:29:04 +000017023 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017024 * @ctxt: a schema validation context
17025 * @options: a combination of xmlSchemaValidOption
17026 *
17027 * Sets the options to be used during the validation.
17028 *
17029 * Returns 0 in case of success, -1 in case of an
17030 * API error.
17031 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017032int
17033xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
17034 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017035
17036{
17037 int i;
17038
17039 if (ctxt == NULL)
17040 return (-1);
17041 /*
17042 * WARNING: Change the start value if adding to the
17043 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017044 * TODO: Is there an other, more easy to maintain,
17045 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017046 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017047 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017048 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017049 xmlSchemaVErr(ctxt, NULL,
17050 XML_SCHEMAV_INTERNAL,
17051 "Internal error: xmlSchemaSetValidOptions, "
17052 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017053 return (-1);
17054 }
17055 }
17056 ctxt->options = options;
17057 return (0);
17058}
17059
17060/**
Daniel Veillard6927b102004-10-27 17:29:04 +000017061 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017062 * @ctxt: a schema validation context
17063 *
William M. Brack21e4ef22005-01-02 09:53:13 +000017064 * Get the validation context options.
17065 *
17066 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017067 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017068int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017069xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
17070
17071{
17072 if (ctxt == NULL)
17073 return (-1);
17074 else
17075 return (ctxt->options);
17076}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017077
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017078
Daniel Veillard259f0df2004-08-18 09:13:18 +000017079/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017080 * xmlSchemaValidateDoc:
17081 * @ctxt: a schema validation context
17082 * @doc: a parsed document tree
17083 *
17084 * Validate a document tree in memory.
17085 *
17086 * Returns 0 if the document is schemas valid, a positive error code
17087 * number otherwise and -1 in case of internal or API error.
17088 */
17089int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017090xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
17091{
Daniel Veillard4255d502002-04-16 15:50:10 +000017092 int ret;
17093
17094 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017095 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017096
17097 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000017098 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017099 ctxt->nberrors = 0;
17100
17101 /*
17102 if (ctxt->schema == NULL) {
17103 xmlSchemaVErr(ctxt, NULL,
17104 XML_SCHEMAV_INTERNAL,
17105 "API error: xmlSchemaValidateDoc, "
17106 "no schema specified and assembling of schemata "
17107 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
17108 "is not enabled.\n", NULL, NULL);
17109 return (-1);
17110 }
17111 */
Daniel Veillard4255d502002-04-16 15:50:10 +000017112 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017113 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000017114}
17115
17116/**
17117 * xmlSchemaValidateStream:
17118 * @ctxt: a schema validation context
17119 * @input: the input to use for reading the data
17120 * @enc: an optional encoding information
17121 * @sax: a SAX handler for the resulting events
17122 * @user_data: the context to provide to the SAX handler.
17123 *
17124 * Validate a document tree in memory.
17125 *
17126 * Returns 0 if the document is schemas valid, a positive error code
17127 * number otherwise and -1 in case of internal or API error.
17128 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017129int
Daniel Veillard4255d502002-04-16 15:50:10 +000017130xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017131 xmlParserInputBufferPtr input, xmlCharEncoding enc,
17132 xmlSAXHandlerPtr sax, void *user_data)
17133{
Daniel Veillard4255d502002-04-16 15:50:10 +000017134 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017135 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017136 ctxt->input = input;
17137 ctxt->enc = enc;
17138 ctxt->sax = sax;
17139 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017140 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017141}
17142
17143#endif /* LIBXML_SCHEMAS_ENABLED */