blob: 0803ebcb434c772b5ae8dc211513f88f14a6874a [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000037
Daniel Veillarda84c0b32003-06-02 16:58:46 +000038/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000039
Daniel Veillard82bbbd42003-05-11 20:16:09 +000040/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000041
Daniel Veillard82bbbd42003-05-11 20:16:09 +000042/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000043
Daniel Veillard118aed72002-09-24 14:13:13 +000044/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000045
Daniel Veillard4255d502002-04-16 15:50:10 +000046/* #define DEBUG_AUTOMATA 1 */
47
Daniel Veillard3646d642004-06-02 19:19:14 +000048/* #define DEBUG_ATTR_VALIDATION 1 */
49
Daniel Veillardc0826a72004-08-10 14:17:33 +000050/* #define DEBUG_UNION_VALIDATION 1 */
51
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define UNBOUNDED (1 << 30)
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
William M. Brack2f2a6632004-08-20 23:09:47 +000059#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000060
Daniel Veillard4255d502002-04-16 15:50:10 +000061/*
62 * The XML Schemas namespaces
63 */
64static const xmlChar *xmlSchemaNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema";
66
67static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
68 "http://www.w3.org/2001/XMLSchema-instance";
69
Daniel Veillardc0826a72004-08-10 14:17:33 +000070static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
71 "Element decl.";
72static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
73 "Element ref.";
74static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
75 "Attribute decl.";
76static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
77 "Attribute ref.";
78static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000079 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000080static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000081 "complex type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000082
Daniel Veillard4255d502002-04-16 15:50:10 +000083#define IS_SCHEMA(node, type) \
84 ((node != NULL) && (node->ns != NULL) && \
85 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
86 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
87
Daniel Veillardc0826a72004-08-10 14:17:33 +000088#define FREE_AND_NULL(str) \
89 if (str != NULL) { \
90 xmlFree(str); \
91 str = NULL; \
92 }
93
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000094#define IS_ANYTYPE(item) \
95 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
96 (item->builtInType == XML_SCHEMAS_ANYTYPE))
97
98#define IS_COMPLEX_TYPE(item) \
99 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
100 (item->builtInType == XML_SCHEMAS_ANYTYPE))
101
102#define IS_SIMPLE_TYPE(item) \
103 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
104 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
105 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
106
Daniel Veillardc0826a72004-08-10 14:17:33 +0000107#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
108#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
109#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define XML_SCHEMAS_PARSE_ERROR 1
112
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000113#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000115
116/*
117* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
118* allow to assemble schemata with
119* the same target namespace from
120* different sources; otherwise, the first
121* encountered schema with a specific target
122* namespace will be used only *
123
124*
125* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
126* locate schemata to be imported
127* using the namespace name; otherwise
128* the location URI will be used */
129
130/*
131* xmlSchemaParserOption:
132*
133* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000135typedef enum {
136 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000137 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000138 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000139 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000140} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000141*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000142
143/*
144XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000145 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
146 int options);
147XMLPUBFUN int XMLCALL
148 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
149
150*/
151
152typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
153typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
154struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000155 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156 int nbItems; /* used for dynamic addition of schemata */
157 int sizeItems; /* used for dynamic addition of schemata */
158};
159
Daniel Veillard4255d502002-04-16 15:50:10 +0000160struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000161 void *userData; /* user specific data block */
162 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
163 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000164 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000165 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000166 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000167
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000168 xmlSchemaPtr topschema; /* The main schema */
169 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
170
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000171 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000172 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000173 int counter;
174
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000175 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000177 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000178
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179 const char *buffer;
180 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000181
Daniel Veillard4255d502002-04-16 15:50:10 +0000182 /*
183 * Used to build complex element content models
184 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000185 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 xmlAutomataStatePtr start;
187 xmlAutomataStatePtr end;
188 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000189
190 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000191 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000192 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
193 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194 xmlSchemaAssemblePtr assemble;
195 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000196 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000197};
198
199
200#define XML_SCHEMAS_ATTR_UNKNOWN 1
201#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000202#define XML_SCHEMAS_ATTR_PROHIBITED 3
203#define XML_SCHEMAS_ATTR_MISSING 4
204#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
205#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000206#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
207#define XML_SCHEMAS_ATTR_DEFAULT 8
Daniel Veillard4255d502002-04-16 15:50:10 +0000208
209typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
210typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
211struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000212 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000213 xmlAttrPtr attr;
214 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000215 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000216 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000217};
218
219/**
220 * xmlSchemaValidCtxt:
221 *
222 * A Schemas validation context
223 */
224
225struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *userData; /* user specific data block */
227 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
228 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000229 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000230
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000231 xmlSchemaPtr schema; /* The schema in use */
232 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlCharEncoding enc;
235 xmlSAXHandlerPtr sax;
236 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 xmlDocPtr myDoc;
239 int err;
240 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000241
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000242 xmlNodePtr node;
243 xmlNodePtr cur;
244 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000246 xmlRegExecCtxtPtr regexp;
247 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248
Daniel Veillard3646d642004-06-02 19:19:14 +0000249 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000250 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000251 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000252 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlNodePtr validationRoot;
255 xmlSchemaParserCtxtPtr pctxt;
256 int xsiAssemble;
Daniel Veillard4255d502002-04-16 15:50:10 +0000257};
258
Daniel Veillard1d913862003-11-21 00:28:39 +0000259/*
260 * These are the entries in the schemas importSchemas hash table
261 */
262typedef struct _xmlSchemaImport xmlSchemaImport;
263typedef xmlSchemaImport *xmlSchemaImportPtr;
264struct _xmlSchemaImport {
265 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000266 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000267 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000268 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000269};
Daniel Veillard4255d502002-04-16 15:50:10 +0000270
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000271/*
272 * These are the entries associated to includes in a schemas
273 */
274typedef struct _xmlSchemaInclude xmlSchemaInclude;
275typedef xmlSchemaInclude *xmlSchemaIncludePtr;
276struct _xmlSchemaInclude {
277 xmlSchemaIncludePtr next;
278
279 const xmlChar *schemaLocation;
280 xmlDocPtr doc;
281};
282
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000283typedef struct _xmlSchemaParticle xmlSchemaParticle;
284typedef xmlSchemaParticle *xmlSchemaParticlePtr;
285struct _xmlSchemaParticle {
286 xmlSchemaTypeType type;
287 xmlSchemaParticlePtr next; /* the next particle if in a list */
288 int minOccurs;
289 int maxOccurs;
290 xmlSchemaTypePtr term;
291};
292
293
294typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
295typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
296struct _xmlSchemaModelGroup {
297 xmlSchemaTypeType type;
298 int compositor; /* one of all, choice or sequence */
299 xmlSchemaParticlePtr particles; /* list of particles */
300 xmlSchemaAnnotPtr annot;
301};
302
303typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
304typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
305struct _xmlSchemaModelGroupDef {
306 xmlSchemaTypeType type;
307 const xmlChar *name;
308 const xmlChar *targetNamespace;
309 xmlSchemaModelGroupPtr modelGroup;
310 xmlSchemaAnnotPtr annot;
311};
312
Daniel Veillard4255d502002-04-16 15:50:10 +0000313/************************************************************************
314 * *
315 * Some predeclarations *
316 * *
317 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000319static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
320 xmlSchemaPtr schema,
321 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000322static void
323xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
324 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
325static const char *
326xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
327static int
328xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000329 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000330 const xmlChar *value,
331 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000332 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000333 int normalize,
334 int checkNodes);
335static int
336xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
337 xmlSchemaElementPtr elemDecl);
338static int
339xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
340 xmlSchemaTypePtr type);
341static int
342xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000343static int
344xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
345 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000346static void
347xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
348 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000349
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000350/************************************************************************
351 * *
352 * Datatype error handlers *
353 * *
354 ************************************************************************/
355
356/**
357 * xmlSchemaPErrMemory:
358 * @node: a context node
359 * @extra: extra informations
360 *
361 * Handle an out of memory condition
362 */
363static void
364xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
365 const char *extra, xmlNodePtr node)
366{
367 if (ctxt != NULL)
368 ctxt->nberrors++;
369 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
370 extra);
371}
372
373/**
374 * xmlSchemaPErr:
375 * @ctxt: the parsing context
376 * @node: the context node
377 * @error: the error code
378 * @msg: the error message
379 * @str1: extra data
380 * @str2: extra data
381 *
382 * Handle a parser error
383 */
384static void
385xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
386 const char *msg, const xmlChar * str1, const xmlChar * str2)
387{
388 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000389 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000390 void *data = NULL;
391
392 if (ctxt != NULL) {
393 ctxt->nberrors++;
394 channel = ctxt->error;
395 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000396 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000397 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000398 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000399 error, XML_ERR_ERROR, NULL, 0,
400 (const char *) str1, (const char *) str2, NULL, 0, 0,
401 msg, str1, str2);
402}
403
404/**
405 * xmlSchemaPErr2:
406 * @ctxt: the parsing context
407 * @node: the context node
408 * @node: the current child
409 * @error: the error code
410 * @msg: the error message
411 * @str1: extra data
412 * @str2: extra data
413 *
414 * Handle a parser error
415 */
416static void
417xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
418 xmlNodePtr child, int error,
419 const char *msg, const xmlChar * str1, const xmlChar * str2)
420{
421 if (child != NULL)
422 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
423 else
424 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
425}
426
Daniel Veillard01fa6152004-06-29 17:04:39 +0000427
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000428/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000429 * xmlSchemaPErrExt:
430 * @ctxt: the parsing context
431 * @node: the context node
432 * @error: the error code
433 * @strData1: extra data
434 * @strData2: extra data
435 * @strData3: extra data
436 * @msg: the message
437 * @str1: extra parameter for the message display
438 * @str2: extra parameter for the message display
439 * @str3: extra parameter for the message display
440 * @str4: extra parameter for the message display
441 * @str5: extra parameter for the message display
442 *
443 * Handle a parser error
444 */
445static void
446xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
447 const xmlChar * strData1, const xmlChar * strData2,
448 const xmlChar * strData3, const char *msg, const xmlChar * str1,
449 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
450 const xmlChar * str5)
451{
452
453 xmlGenericErrorFunc channel = NULL;
454 xmlStructuredErrorFunc schannel = NULL;
455 void *data = NULL;
456
457 if (ctxt != NULL) {
458 ctxt->nberrors++;
459 channel = ctxt->error;
460 data = ctxt->userData;
461 schannel = ctxt->serror;
462 }
463 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
464 error, XML_ERR_ERROR, NULL, 0,
465 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000466 (const char *) strData3, 0, 0, msg, str1, str2,
467 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000468}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000469
Daniel Veillard3646d642004-06-02 19:19:14 +0000470
471/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000472 * xmlSchemaVTypeErrMemory:
473 * @node: a context node
474 * @extra: extra informations
475 *
476 * Handle an out of memory condition
477 */
478static void
479xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
480 const char *extra, xmlNodePtr node)
481{
482 if (ctxt != NULL) {
483 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000484 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000485 }
486 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
487 extra);
488}
489
490/**
491 * xmlSchemaVErr3:
492 * @ctxt: the validation context
493 * @node: the context node
494 * @error: the error code
495 * @msg: the error message
496 * @str1: extra data
497 * @str2: extra data
498 * @str3: extra data
499 *
500 * Handle a validation error
501 */
502static void
503xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
504 const char *msg, const xmlChar *str1, const xmlChar *str2,
505 const xmlChar *str3)
506{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000507 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000508 xmlGenericErrorFunc channel = NULL;
509 void *data = NULL;
510
511 if (ctxt != NULL) {
512 ctxt->nberrors++;
513 ctxt->err = error;
514 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000515 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000516 data = ctxt->userData;
517 }
518 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000519 /* Removed, since the old schema error codes have been
520 * substituted for the global error codes.
521 *
522 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
523 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000524 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000525 error, XML_ERR_ERROR, NULL, 0,
526 (const char *) str1, (const char *) str2,
527 (const char *) str3, 0, 0,
528 msg, str1, str2, str3);
529}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000530
531/**
532 * xmlSchemaVErrExt:
533 * @ctxt: the validation context
534 * @node: the context node
535 * @error: the error code
536 * @msg: the message
537 * @str1: extra parameter for the message display
538 * @str2: extra parameter for the message display
539 * @str3: extra parameter for the message display
540 * @str4: extra parameter for the message display
541 * @str5: extra parameter for the message display
542 *
543 * Handle a validation error
544 */
545static void
546xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
547 const char *msg, const xmlChar * str1,
548 const xmlChar * str2, const xmlChar * str3,
549 const xmlChar * str4, const xmlChar * str5)
550{
551 xmlStructuredErrorFunc schannel = NULL;
552 xmlGenericErrorFunc channel = NULL;
553 void *data = NULL;
554
555 if (ctxt != NULL) {
556 ctxt->nberrors++;
557 ctxt->err = error;
558 channel = ctxt->error;
559 schannel = ctxt->serror;
560 data = ctxt->userData;
561 }
562 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000563 /* Removed, since the old schema error codes have been
564 * substituted for the global error codes.
565 *
566 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
567 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000568 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
569 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
570 msg, str1, str2, str3, str4, str5);
571}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572/**
573 * xmlSchemaVErr:
574 * @ctxt: the validation context
575 * @node: the context node
576 * @error: the error code
577 * @msg: the error message
578 * @str1: extra data
579 * @str2: extra data
580 *
581 * Handle a validation error
582 */
583static void
584xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
585 const char *msg, const xmlChar * str1, const xmlChar * str2)
586{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000587 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000588 xmlGenericErrorFunc channel = NULL;
589 void *data = NULL;
590
591 if (ctxt != NULL) {
592 ctxt->nberrors++;
593 ctxt->err = error;
594 channel = ctxt->error;
595 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000596 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000597 }
598 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000599 /* Removed, since the old schema error codes have been
600 * substituted for the global error codes.
601 *
602 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
603 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000604 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000605 error, XML_ERR_ERROR, NULL, 0,
606 (const char *) str1, (const char *) str2, NULL, 0, 0,
607 msg, str1, str2);
608}
Daniel Veillard4255d502002-04-16 15:50:10 +0000609
Daniel Veillardc0826a72004-08-10 14:17:33 +0000610/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000611 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000612 * @attr: the attribute declaration/use
613 *
614 * Returns the name of the attribute; if the attribute
615 * is a reference, the name of the referenced global type will be returned.
616 */
617static const xmlChar *
618xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
619{
620 if (attr->ref != NULL)
621 return(attr->ref);
622 else
623 return(attr->name);
624}
625
626/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000627 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000628 * @type: the type (element or attribute)
629 *
630 * Returns the target namespace URI of the type; if the type is a reference,
631 * the target namespace of the referenced type will be returned.
632 */
633static const xmlChar *
634xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
635{
636 if (attr->ref != NULL)
637 return (attr->refNs);
638 else
639 return(attr->targetNamespace);
640}
641
642/**
643 * xmlSchemaFormatNsUriLocal:
644 * @buf: the string buffer
645 * @uri: the namespace URI
646 * @local: the local name
647 *
648 * Returns a representation of the given URI used
649 * for error reports.
650 *
651 * Returns an empty string, if @ns is NULL, a formatted
652 * string otherwise.
653 */
654static const xmlChar*
655xmlSchemaFormatNsUriLocal(xmlChar **buf,
656 const xmlChar *uri, const xmlChar *local)
657{
658 if (*buf != NULL)
659 xmlFree(*buf);
660 if (uri == NULL) {
661 *buf = xmlStrdup(BAD_CAST "{'");
662 *buf = xmlStrcat(*buf, local);
663 } else {
664 *buf = xmlStrdup(BAD_CAST "{'");
665 *buf = xmlStrcat(*buf, uri);
666 *buf = xmlStrcat(*buf, BAD_CAST "', '");
667 *buf = xmlStrcat(*buf, local);
668 }
669 *buf = xmlStrcat(*buf, BAD_CAST "'}");
670 return ((const xmlChar *) *buf);
671}
672
673/**
674 * xmlSchemaFormatNsPrefixLocal:
675 * @buf: the string buffer
676 * @ns: the namespace
677 * @local: the local name
678 *
679 * Returns a representation of the given URI used
680 * for error reports.
681 *
682 * Returns an empty string, if @ns is NULL, a formatted
683 * string otherwise.
684 */
685static const xmlChar*
686xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
687 xmlNsPtr ns, const xmlChar *local)
688{
689 if (*buf != NULL) {
690 xmlFree(*buf);
691 *buf = NULL;
692 }
693 if ((ns == NULL) || (ns->prefix == NULL))
694 return(local);
695 else {
696 *buf = xmlStrdup(ns->prefix);
697 *buf = xmlStrcat(*buf, BAD_CAST ":");
698 *buf = xmlStrcat(*buf, local);
699 }
700 return ((const xmlChar *) *buf);
701}
702
703/**
704 * xmlSchemaFormatItemForReport:
705 * @buf: the string buffer
706 * @itemDes: the designation of the item
707 * @itemName: the name of the item
708 * @item: the item as an object
709 * @itemNode: the node of the item
710 * @local: the local name
711 * @parsing: if the function is used during the parse
712 *
713 * Returns a representation of the given item used
714 * for error reports.
715 *
716 * The following order is used to build the resulting
717 * designation if the arguments are not NULL:
718 * 1a. If itemDes not NULL -> itemDes
719 * 1b. If (itemDes not NULL) and (itemName not NULL)
720 * -> itemDes + itemName
721 * 2. If the preceding was NULL and (item not NULL) -> item
722 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
723 *
724 * If the itemNode is an attribute node, the name of the attribute
725 * will be appended to the result.
726 *
727 * Returns the formatted string and sets @buf to the resulting value.
728 */
729static xmlChar*
730xmlSchemaFormatItemForReport(xmlChar **buf,
731 const xmlChar *itemDes,
732 xmlSchemaTypePtr item,
733 xmlNodePtr itemNode,
734 int parsing)
735{
736 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000737 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000738
739 if (*buf != NULL) {
740 xmlFree(*buf);
741 *buf = NULL;
742 }
743
William M. Brack2f2a6632004-08-20 23:09:47 +0000744 if (itemDes != NULL) {
745 *buf = xmlStrdup(itemDes);
746 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000747 if (item->type == XML_SCHEMA_TYPE_BASIC) {
748 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
749 *buf = xmlStrdup(BAD_CAST "'anyType'");
750 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
751 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
752 else {
753 /* *buf = xmlStrdup(BAD_CAST "bi "); */
754 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
755 *buf = xmlStrdup(BAD_CAST "'");
756 *buf = xmlStrcat(*buf, item->name);
757 *buf = xmlStrcat(*buf, BAD_CAST "'");
758 }
759 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
760 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
761 *buf = xmlStrdup(xmlSchemaElemDesST);
762 *buf = xmlStrcat(*buf, BAD_CAST " '");
763 *buf = xmlStrcat(*buf, item->name);
764 *buf = xmlStrcat(*buf, BAD_CAST "'");
765 } else {
766 *buf = xmlStrdup(xmlSchemaElemDesST);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000767 /* Local types will get to name
768 *buf = xmlStrcat(*buf, BAD_CAST " ");
769 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000770 }
771 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
772 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
773 *buf = xmlStrdup(xmlSchemaElemDesCT);
774 *buf = xmlStrcat(*buf, BAD_CAST " '");
775 *buf = xmlStrcat(*buf, item->name);
776 *buf = xmlStrcat(*buf, BAD_CAST "'");
777 } else {
778 *buf = xmlStrdup(xmlSchemaElemDesCT);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000779 /* Local types will get to name
780 *buf = xmlStrcat(*buf, BAD_CAST " ");
781 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000782 }
783 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
784 xmlSchemaAttributePtr attr;
785
786 attr = (xmlSchemaAttributePtr) item;
787 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
788 (attr->ref == NULL)) {
789 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
790 *buf = xmlStrcat(*buf, BAD_CAST " '");
791 *buf = xmlStrcat(*buf, attr->name);
792 *buf = xmlStrcat(*buf, BAD_CAST "'");
793 } else {
794 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
795 *buf = xmlStrcat(*buf, BAD_CAST " '");
796 *buf = xmlStrcat(*buf, attr->refPrefix);
797 *buf = xmlStrcat(*buf, BAD_CAST ":");
798 *buf = xmlStrcat(*buf, attr->ref);
799 *buf = xmlStrcat(*buf, BAD_CAST "'");
800 }
801 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
802 xmlSchemaElementPtr elem;
803
804 elem = (xmlSchemaElementPtr) item;
805 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
806 (elem->ref == NULL)) {
807 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
808 *buf = xmlStrcat(*buf, BAD_CAST " '");
809 *buf = xmlStrcat(*buf, elem->name);
810 *buf = xmlStrcat(*buf, BAD_CAST "'");
811 } else {
812 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
813 *buf = xmlStrcat(*buf, BAD_CAST " '");
814 *buf = xmlStrcat(*buf, elem->refPrefix);
815 *buf = xmlStrcat(*buf, BAD_CAST ":");
816 *buf = xmlStrcat(*buf, elem->ref);
817 *buf = xmlStrcat(*buf, BAD_CAST "'");
818 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000819 } else
820 named = 0;
821 } else
822 named = 0;
823
824 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000825 xmlNodePtr elem;
826
827 if (itemNode->type == XML_ATTRIBUTE_NODE)
828 elem = itemNode->parent;
829 else
830 elem = itemNode;
831 *buf = xmlStrdup(BAD_CAST "Element '");
832 if (parsing)
833 *buf = xmlStrcat(*buf, elem->name);
834 else
835 *buf = xmlStrcat(*buf,
836 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
837 *buf = xmlStrcat(*buf, BAD_CAST "'");
838 }
839 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
840 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
841 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
842 itemNode->ns, itemNode->name));
843 *buf = xmlStrcat(*buf, BAD_CAST "'");
844 }
845 FREE_AND_NULL(str);
846
847 return (*buf);
848}
849
850/**
851 * xmlSchemaPFormatItemDes:
852 * @buf: the string buffer
853 * @item: the item as a schema object
854 * @itemNode: the item as a node
855 *
856 * If the pointer to @buf is not NULL and @but holds no value,
857 * the value is set to a item designation using
858 * xmlSchemaFormatItemForReport. This one avoids adding
859 * an attribute designation postfix.
860 *
861 * Returns a string of all enumeration elements.
862 */
863static void
864xmlSchemaPRequestItemDes(xmlChar **buf,
865 xmlSchemaTypePtr item,
866 xmlNodePtr itemNode)
867{
868 if ((buf == 0) || (*buf != NULL))
869 return;
870 if (itemNode->type == XML_ATTRIBUTE_NODE)
871 itemNode = itemNode->parent;
872 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
873}
874
875/**
876 * xmlSchemaFormatFacetEnumSet:
877 * @buf: the string buffer
878 * @type: the type holding the enumeration facets
879 *
880 * Builds a string consisting of all enumeration elements.
881 *
882 * Returns a string of all enumeration elements.
883 */
884static const xmlChar *
885xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
886{
887 xmlSchemaFacetLinkPtr link;
888
889 if (*buf != NULL)
890 xmlFree(*buf);
891 *buf = NULL;
892 for (link = type->facetSet; link != NULL; link = link->next) {
893 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
894 if (*buf == NULL) {
895 *buf = xmlStrdup(BAD_CAST "'");
896 *buf = xmlStrcat(*buf, link->facet->value);
897 *buf = xmlStrcat(*buf, BAD_CAST "'");
898 } else {
899 *buf = xmlStrcat(*buf, BAD_CAST ", '");
900 *buf = xmlStrcat(*buf, link->facet->value);
901 *buf = xmlStrcat(*buf, BAD_CAST "'");
902 }
903 }
904 }
905 return ((const xmlChar *) *buf);
906}
907
908/**
909 * xmlSchemaVFacetErr:
910 * @ctxt: the schema validation context
911 * @error: the error code
912 * @node: the node to be validated
913 * @value: the value of the node
914 * @type: the type holding the facet
915 * @facet: the facet
916 * @message: the error message of NULL
917 * @str1: extra data
918 * @str2: extra data
919 * @str3: extra data
920 *
921 * Reports a facet validation error.
922 * TODO: Should this report the value of an element as well?
923 */
924static void
925xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
926 xmlParserErrors error,
927 xmlNodePtr node,
928 const xmlChar *value,
929 unsigned long length,
930 xmlSchemaTypePtr type,
931 xmlSchemaFacetPtr facet,
932 const char *message,
933 const xmlChar *str1,
934 const xmlChar *str2,
935 const xmlChar *str3)
936{
937 xmlChar *str = NULL, *msg = NULL;
938 xmlSchemaTypeType facetType;
939
940 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
941 msg = xmlStrcat(msg, BAD_CAST " [");
942 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
943 msg = xmlStrcat(msg, BAD_CAST ", facet '");
944 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
945 facetType = XML_SCHEMA_FACET_ENUMERATION;
946 /*
947 * If enumerations are validated, one must not expect the
948 * facet to be given.
949 */
950 } else
951 facetType = facet->type;
952 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
953 msg = xmlStrcat(msg, BAD_CAST "']: ");
954 if (message == NULL) {
955 /*
956 * Use a default message.
957 */
958 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
959 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
960 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
961
962 char len[25], actLen[25];
963
964 /* FIXME, TODO: What is the max expected string length of the
965 * this value?
966 */
967 if (node->type == XML_ATTRIBUTE_NODE)
968 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
969 else
970 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
971
972 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
973 snprintf(actLen, 24, "%lu", length);
974
975 if (facetType == XML_SCHEMA_FACET_LENGTH)
976 msg = xmlStrcat(msg,
977 BAD_CAST "this differs from the allowed length of '%s'.\n");
978 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
979 msg = xmlStrcat(msg,
980 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
981 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
982 msg = xmlStrcat(msg,
983 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
984
985 if (node->type == XML_ATTRIBUTE_NODE)
986 xmlSchemaVErrExt(ctxt, node, error,
987 (const char *) msg,
988 value, (const xmlChar *) actLen, (const xmlChar *) len,
989 NULL, NULL);
990 else
991 xmlSchemaVErr(ctxt, node, error,
992 (const char *) msg,
993 (const xmlChar *) actLen, (const xmlChar *) len);
994
995 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
996 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
997 "of the set {%s}.\n");
998 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
999 xmlSchemaFormatFacetEnumSet(&str, type));
1000 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1001 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1002 "by the pattern '%s'.\n");
1003 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1004 facet->value);
1005 } else if (node->type == XML_ATTRIBUTE_NODE) {
1006 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1007 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1008 } else {
1009 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1010 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1011 }
1012 } else {
1013 msg = xmlStrcat(msg, (const xmlChar *) message);
1014 msg = xmlStrcat(msg, BAD_CAST ".\n");
1015 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1016 }
1017 FREE_AND_NULL(str)
1018 xmlFree(msg);
1019}
1020
1021/**
1022 * xmlSchemaVSimpleTypeErr:
1023 * @ctxt: the schema validation context
1024 * @error: the error code
1025 * @type: the type used for validation
1026 * @node: the node containing the validated value
1027 * @value: the validated value
1028 *
1029 * Reports a simple type validation error.
1030 * TODO: Should this report the value of an element as well?
1031 */
1032static void
1033xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1034 xmlParserErrors error,
1035 xmlNodePtr node,
1036 const xmlChar *value,
1037 xmlSchemaTypePtr type)
1038{
1039 xmlChar *str = NULL, *msg = NULL;
1040
1041 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1042 msg = xmlStrcat(msg, BAD_CAST " [");
1043 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1044 if (node->type == XML_ATTRIBUTE_NODE) {
1045 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1046 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1047 } else {
1048 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1049 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1050 }
1051 FREE_AND_NULL(str)
1052 xmlFree(msg);
1053}
1054
1055/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001056 * xmlSchemaVComplexTypeErr:
1057 * @ctxt: the schema validation context
1058 * @error: the error code
1059 * @node: the node containing the validated value
1060 * @type: the complex type used for validation
1061 * @message: the error message
1062 *
1063 * Reports a complex type validation error.
1064 */
1065static void
1066xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1067 xmlParserErrors error,
1068 xmlNodePtr node,
1069 xmlSchemaTypePtr type,
1070 const char *message)
1071{
1072 xmlChar *str = NULL, *msg = NULL;
1073
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001074 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001075 /* Specify the complex type only if it is global. */
1076 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001077 msg = xmlStrcat(msg, BAD_CAST " [");
1078 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1079 msg = xmlStrcat(msg, BAD_CAST "]");
1080 }
1081 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
William M. Brack2f2a6632004-08-20 23:09:47 +00001082 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
1083 (const xmlChar *) message, NULL);
1084 FREE_AND_NULL(str)
1085 xmlFree(msg);
1086}
1087
1088/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001089 * xmlSchemaPMissingAttrErr:
1090 * @ctxt: the schema validation context
1091 * @ownerDes: the designation of the owner
1092 * @ownerName: the name of the owner
1093 * @ownerItem: the owner as a schema object
1094 * @ownerElem: the owner as an element node
1095 * @node: the parent element node of the missing attribute node
1096 * @type: the corresponding type of the attribute node
1097 *
1098 * Reports an illegal attribute.
1099 */
1100static void
1101xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1102 xmlParserErrors error,
1103 xmlChar **ownerDes,
1104 xmlSchemaTypePtr ownerItem,
1105 xmlNodePtr ownerElem,
1106 const char *name,
1107 const char *message)
1108{
1109 xmlChar *des = NULL;
1110
1111 if (ownerDes == NULL)
1112 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1113 else if (*ownerDes == NULL) {
1114 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1115 des = *ownerDes;
1116 } else
1117 des = *ownerDes;
1118 if (message != NULL)
1119 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1120 else
1121 xmlSchemaPErr(ctxt, ownerElem, error,
1122 "%s: The attribute '%s' is required but missing.\n",
1123 BAD_CAST des, BAD_CAST name);
1124 if (ownerDes == NULL)
1125 FREE_AND_NULL(des);
1126}
1127
William M. Brack2f2a6632004-08-20 23:09:47 +00001128/**
1129 * xmlSchemaCompTypeToString:
1130 * @type: the type of the schema item
1131 *
1132 * Returns the component name of a schema item.
1133 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001134static const char *
1135xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1136{
1137 switch (type) {
1138 case XML_SCHEMA_TYPE_SIMPLE:
1139 return("simple type definition");
1140 case XML_SCHEMA_TYPE_COMPLEX:
1141 return("complex type definition");
1142 case XML_SCHEMA_TYPE_ELEMENT:
1143 return("element declaration");
1144 case XML_SCHEMA_TYPE_ATTRIBUTE:
1145 return("attribute declaration");
1146 case XML_SCHEMA_TYPE_GROUP:
1147 return("model group definition");
1148 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1149 return("attribute group definition");
1150 case XML_SCHEMA_TYPE_NOTATION:
1151 return("notation declaration");
1152 default:
1153 return("Not a schema component");
1154 }
1155}
1156/**
1157 * xmlSchemaPResCompAttrErr:
1158 * @ctxt: the schema validation context
1159 * @error: the error code
1160 * @ownerDes: the designation of the owner
1161 * @ownerItem: the owner as a schema object
1162 * @ownerElem: the owner as an element node
1163 * @name: the name of the attribute holding the QName
1164 * @refName: the referenced local name
1165 * @refURI: the referenced namespace URI
1166 * @message: optional message
1167 *
1168 * Used to report QName attribute values that failed to resolve
1169 * to schema components.
1170 */
1171static void
1172xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1173 xmlParserErrors error,
1174 xmlChar **ownerDes,
1175 xmlSchemaTypePtr ownerItem,
1176 xmlNodePtr ownerElem,
1177 const char *name,
1178 const xmlChar *refName,
1179 const xmlChar *refURI,
1180 xmlSchemaTypeType refType,
1181 const char *refTypeStr)
1182{
1183 xmlChar *des = NULL, *strA = NULL;
1184
1185 if (ownerDes == NULL)
1186 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1187 else if (*ownerDes == NULL) {
1188 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1189 des = *ownerDes;
1190 } else
1191 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001192 if (refTypeStr == NULL)
1193 refTypeStr = xmlSchemaCompTypeToString(refType);
1194 xmlSchemaPErrExt(ctxt, ownerElem, error,
1195 NULL, NULL, NULL,
1196 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1197 "%s.\n", BAD_CAST des, BAD_CAST name,
1198 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1199 BAD_CAST refTypeStr, NULL);
1200 if (ownerDes == NULL)
1201 FREE_AND_NULL(des)
1202 FREE_AND_NULL(strA)
1203}
1204
William M. Brack2f2a6632004-08-20 23:09:47 +00001205/**
1206 * xmlSchemaPCustomAttrErr:
1207 * @ctxt: the schema parser context
1208 * @error: the error code
1209 * @ownerDes: the designation of the owner
1210 * @ownerItem: the owner as a schema object
1211 * @attr: the illegal attribute node
1212 *
1213 * Reports an illegal attribute during the parse.
1214 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001215static void
1216xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001217 xmlParserErrors error,
1218 xmlChar **ownerDes,
1219 xmlSchemaTypePtr ownerItem,
1220 xmlAttrPtr attr,
1221 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001222{
1223 xmlChar *des = NULL;
1224
1225 if (ownerDes == NULL)
1226 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1227 else if (*ownerDes == NULL) {
1228 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1229 des = *ownerDes;
1230 } else
1231 des = *ownerDes;
1232 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1233 "%s, attribute '%s': %s.\n",
1234 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1235 if (ownerDes == NULL)
1236 FREE_AND_NULL(des);
1237}
1238
1239/**
1240 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001241 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001242 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001243 * @ownerDes: the designation of the attribute's owner
1244 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001245 * @attr: the illegal attribute node
1246 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001247 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001248 */
1249static void
1250xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1251 xmlParserErrors error,
1252 xmlChar **ownerDes,
1253 xmlSchemaTypePtr ownerItem,
1254 xmlAttrPtr attr)
1255{
1256 xmlChar *des = NULL, *strA = NULL;
1257
1258 if (ownerDes == NULL)
1259 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1260 else if (*ownerDes == NULL) {
1261 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1262 des = *ownerDes;
1263 } else
1264 des = *ownerDes;
1265 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1266 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1267 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1268 if (ownerDes == NULL)
1269 FREE_AND_NULL(des);
1270 FREE_AND_NULL(strA);
1271}
1272
William M. Brack2f2a6632004-08-20 23:09:47 +00001273/**
1274 * xmlSchemaPAquireDes:
1275 * @des: the first designation
1276 * @itemDes: the second designation
1277 * @item: the schema item
1278 * @itemElem: the node of the schema item
1279 *
1280 * Creates a designation for an item.
1281 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001282static void
1283xmlSchemaPAquireDes(xmlChar **des,
1284 xmlChar **itemDes,
1285 xmlSchemaTypePtr item,
1286 xmlNodePtr itemElem)
1287{
1288 if (itemDes == NULL)
1289 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1290 else if (*itemDes == NULL) {
1291 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1292 *des = *itemDes;
1293 } else
1294 *des = *itemDes;
1295}
1296
William M. Brack2f2a6632004-08-20 23:09:47 +00001297/**
1298 * xmlSchemaPCustomErr:
1299 * @ctxt: the schema parser context
1300 * @error: the error code
1301 * @itemDes: the designation of the schema item
1302 * @item: the schema item
1303 * @itemElem: the node of the schema item
1304 * @message: the error message
1305 * @str1: an optional param for the error message
1306 * @str2: an optional param for the error message
1307 * @str3: an optional param for the error message
1308 *
1309 * Reports an error during parsing.
1310 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001311static void
1312xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1313 xmlParserErrors error,
1314 xmlChar **itemDes,
1315 xmlSchemaTypePtr item,
1316 xmlNodePtr itemElem,
1317 const char *message,
1318 const xmlChar *str1,
1319 const xmlChar *str2,
1320 const xmlChar *str3)
1321{
1322 xmlChar *des = NULL, *msg = NULL;
1323
1324 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1325 msg = xmlStrdup(BAD_CAST "%s: ");
1326 msg = xmlStrcat(msg, (const xmlChar *) message);
1327 msg = xmlStrcat(msg, BAD_CAST ".\n");
1328 if ((itemElem == NULL) && (item != NULL))
1329 itemElem = item->node;
1330 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1331 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1332 if (itemDes == NULL)
1333 FREE_AND_NULL(des);
1334 FREE_AND_NULL(msg);
1335}
1336
William M. Brack2f2a6632004-08-20 23:09:47 +00001337/**
1338 * xmlSchemaPCustomErr:
1339 * @ctxt: the schema parser context
1340 * @error: the error code
1341 * @itemDes: the designation of the schema item
1342 * @item: the schema item
1343 * @itemElem: the node of the schema item
1344 * @message: the error message
1345 * @str1: the optional param for the error message
1346 *
1347 * Reports an error during parsing.
1348 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001349static void
1350xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1351 xmlParserErrors error,
1352 xmlChar **itemDes,
1353 xmlSchemaTypePtr item,
1354 xmlNodePtr itemElem,
1355 const char *message,
1356 const xmlChar *str1)
1357{
1358 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1359 str1, NULL, NULL);
1360}
1361
William M. Brack2f2a6632004-08-20 23:09:47 +00001362/**
1363 * xmlSchemaPAttrUseErr:
1364 * @ctxt: the schema parser context
1365 * @error: the error code
1366 * @itemDes: the designation of the schema type
1367 * @item: the schema type
1368 * @itemElem: the node of the schema type
1369 * @attr: the invalid schema attribute
1370 * @message: the error message
1371 * @str1: the optional param for the error message
1372 *
1373 * Reports an attribute use error during parsing.
1374 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001375static void
1376xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1377 xmlParserErrors error,
1378 xmlChar **itemDes,
1379 xmlSchemaTypePtr item,
1380 xmlNodePtr itemElem,
1381 const xmlSchemaAttributePtr attr,
1382 const char *message,
1383 const xmlChar *str1)
1384{
1385 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1386
1387 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1388 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1389 xmlSchemaGetAttrName(attr));
1390 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1391 msg = xmlStrcat(msg, (const xmlChar *) message);
1392 msg = xmlStrcat(msg, BAD_CAST ".\n");
1393 if ((itemElem == NULL) && (item != NULL))
1394 itemElem = item->node;
1395 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1396 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1397 if (itemDes == NULL)
1398 FREE_AND_NULL(des);
1399 FREE_AND_NULL(strA);
1400 xmlFree(msg);
1401}
1402
William M. Brack2f2a6632004-08-20 23:09:47 +00001403/**
1404 * xmlSchemaPIllegalFacetAtomicErr:
1405 * @ctxt: the schema parser context
1406 * @error: the error code
1407 * @itemDes: the designation of the type
1408 * @item: the schema type
1409 * @baseItem: the base type of type
1410 * @facet: the illegal facet
1411 *
1412 * Reports an illegal facet for atomic simple types.
1413 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001414static void
1415xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1416 xmlParserErrors error,
1417 xmlChar **itemDes,
1418 xmlSchemaTypePtr item,
1419 xmlSchemaTypePtr baseItem,
1420 xmlSchemaFacetPtr facet)
1421{
1422 xmlChar *des = NULL, *strT = NULL;
1423
1424 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1425 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1426 "%s: The facet '%s' is not allowed on types derived from the "
1427 "type %s.\n",
1428 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1429 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1430 NULL, NULL);
1431 if (itemDes == NULL)
1432 FREE_AND_NULL(des);
1433 FREE_AND_NULL(strT);
1434}
1435
William M. Brack2f2a6632004-08-20 23:09:47 +00001436/**
1437 * xmlSchemaPIllegalFacetListUnionErr:
1438 * @ctxt: the schema parser context
1439 * @error: the error code
1440 * @itemDes: the designation of the schema item involved
1441 * @item: the schema item involved
1442 * @facet: the illegal facet
1443 *
1444 * Reports an illegal facet for <list> and <union>.
1445 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001446static void
1447xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1448 xmlParserErrors error,
1449 xmlChar **itemDes,
1450 xmlSchemaTypePtr item,
1451 xmlSchemaFacetPtr facet)
1452{
1453 xmlChar *des = NULL, *strT = NULL;
1454
1455 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1456 xmlSchemaPErr(ctxt, item->node, error,
1457 "%s: The facet '%s' is not allowed.\n",
1458 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1459 if (itemDes == NULL)
1460 FREE_AND_NULL(des);
1461 FREE_AND_NULL(strT);
1462}
1463
1464/**
1465 * xmlSchemaPMutualExclAttrErr:
1466 * @ctxt: the schema validation context
1467 * @error: the error code
1468 * @elemDes: the designation of the parent element node
1469 * @attr: the bad attribute node
1470 * @type: the corresponding type of the attribute node
1471 *
1472 * Reports an illegal attribute.
1473 */
1474static void
1475xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1476 xmlParserErrors error,
1477 xmlChar **ownerDes,
1478 xmlSchemaTypePtr ownerItem,
1479 xmlAttrPtr attr,
1480 const char *name1,
1481 const char *name2)
1482{
1483 xmlChar *des = NULL;
1484
1485 if (ownerDes == NULL)
1486 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1487 else if (*ownerDes == NULL) {
1488 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1489 des = *ownerDes;
1490 } else
1491 des = *ownerDes;
1492 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1493 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1494 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1495 if (ownerDes == NULL)
1496 FREE_AND_NULL(des)
1497}
1498
1499/**
1500 * xmlSchemaPSimpleTypeErr:
1501 * @ctxt: the schema validation context
1502 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001503 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001504 * @ownerDes: the designation of the owner
1505 * @ownerItem: the schema object if existent
1506 * @node: the validated node
1507 * @value: the validated value
1508 *
1509 * Reports a simple type validation error.
1510 * TODO: Should this report the value of an element as well?
1511 */
1512static void
1513xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1514 xmlParserErrors error,
1515 xmlChar **ownerDes,
1516 xmlSchemaTypePtr ownerItem,
1517 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001518 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001519 const char *typeDes,
1520 const xmlChar *value,
1521 const char *message,
1522 const xmlChar *str1,
1523 const xmlChar *str2)
1524{
William M. Brack2f2a6632004-08-20 23:09:47 +00001525 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001526
1527 if (ownerDes == NULL)
1528 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1529 else if (*ownerDes == NULL) {
1530 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1531 des = *ownerDes;
1532 } else
1533 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001534 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001535 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001536 if (message == NULL) {
1537 /*
1538 * Use default messages.
1539 */
1540 if (node->type == XML_ATTRIBUTE_NODE) {
1541 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1542 "%s, attribute '%s' [%s]: The value '%s' is not "
1543 "valid.\n",
1544 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1545 node->name), BAD_CAST typeDes, value, NULL);
1546 } else {
1547 xmlSchemaPErr(ctxt, node, error,
1548 "%s [%s]: The character content is not valid.\n",
1549 BAD_CAST des, BAD_CAST typeDes);
1550 }
1551 } else {
1552 xmlChar *msg;
1553
1554 msg = xmlStrdup(BAD_CAST "%s");
1555 if (node->type == XML_ATTRIBUTE_NODE)
1556 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1557 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1558 msg = xmlStrcat(msg, (const xmlChar *) message);
1559 msg = xmlStrcat(msg, BAD_CAST ".\n");
1560 if (node->type == XML_ATTRIBUTE_NODE) {
1561 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1562 (const char *) msg,
1563 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1564 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1565 } else {
1566 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1567 (const char *) msg,
1568 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1569 }
1570 xmlFree(msg);
1571 }
1572 /* Cleanup. */
1573 FREE_AND_NULL(strA)
1574 FREE_AND_NULL(strT)
1575 if (ownerDes == NULL)
1576 FREE_AND_NULL(des)
1577}
1578
William M. Brack2f2a6632004-08-20 23:09:47 +00001579/**
1580 * xmlSchemaPContentErr:
1581 * @ctxt: the schema parser context
1582 * @error: the error code
1583 * @onwerDes: the designation of the holder of the content
1584 * @ownerItem: the owner item of the holder of the content
1585 * @ownerElem: the node of the holder of the content
1586 * @child: the invalid child node
1587 * @message: the optional error message
1588 * @content: the optional string describing the correct content
1589 *
1590 * Reports an error concerning the content of a schema element.
1591 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001592static void
1593xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1594 xmlParserErrors error,
1595 xmlChar **ownerDes,
1596 xmlSchemaTypePtr ownerItem,
1597 xmlNodePtr ownerElem,
1598 xmlNodePtr child,
1599 const char *message,
1600 const char *content)
1601{
1602 xmlChar *des = NULL;
1603
1604 if (ownerDes == NULL)
1605 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1606 else if (*ownerDes == NULL) {
1607 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1608 des = *ownerDes;
1609 } else
1610 des = *ownerDes;
1611 if (message != NULL)
1612 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1613 "%s: %s.\n",
1614 BAD_CAST des, BAD_CAST message);
1615 else {
1616 if (content != NULL) {
1617 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1618 "%s: The content is not valid. Expected is %s.\n",
1619 BAD_CAST des, BAD_CAST content);
1620 } else {
1621 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1622 "%s: The content is not valid.\n",
1623 BAD_CAST des, NULL);
1624 }
1625 }
1626 if (ownerDes == NULL)
1627 FREE_AND_NULL(des)
1628}
1629
1630/**
1631 * xmlSchemaVIllegalAttrErr:
1632 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001633 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001634 * @attr: the illegal attribute node
1635 *
1636 * Reports an illegal attribute.
1637 */
1638static void
1639xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001640 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001641 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001642{
1643 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001644
1645 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1646 error,
1647 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001648 "%s: The attribute '%s' is not allowed.\n",
1649 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1650 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1651 FREE_AND_NULL(strE)
1652 FREE_AND_NULL(strA)
1653}
1654
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001655
1656static int
1657xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1658{
1659 switch (item->type) {
1660 case XML_SCHEMA_TYPE_COMPLEX:
1661 case XML_SCHEMA_TYPE_SIMPLE:
1662 case XML_SCHEMA_TYPE_GROUP:
1663 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1664 return(1);
1665 break;
1666 case XML_SCHEMA_TYPE_ELEMENT:
1667 if ( ((xmlSchemaElementPtr) item)->flags &
1668 XML_SCHEMAS_ELEM_GLOBAL)
1669 return(1);
1670 break;
1671 case XML_SCHEMA_TYPE_ATTRIBUTE:
1672 if ( ((xmlSchemaAttributePtr) item)->flags &
1673 XML_SCHEMAS_ATTR_GLOBAL)
1674 return(1);
1675 break;
1676 /* Note that attribute groups are always global. */
1677 default:
1678 return(1);
1679 }
1680 return (0);
1681}
1682
William M. Brack2f2a6632004-08-20 23:09:47 +00001683/**
1684 * xmlSchemaVCustomErr:
1685 * @ctxt: the schema validation context
1686 * @error: the error code
1687 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001688 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001689 * @message: the error message
1690 * @str1: the optional param for the message
1691 *
1692 * Reports a validation error.
1693 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001694static void
1695xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1696 xmlParserErrors error,
1697 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001698 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699 const char *message,
1700 const xmlChar *str1)
1701{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001702 xmlChar *msg = NULL, *str = NULL;
1703
1704 if (node == NULL) {
1705 xmlSchemaVErr(ctxt, NULL,
1706 XML_SCHEMAV_INTERNAL,
1707 "Internal error: xmlSchemaVCustomErr, no node "
1708 "given.\n", NULL, NULL);
1709 return;
1710 }
1711 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1712 if (node->type != XML_DOCUMENT_NODE) {
1713 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001714 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001715 msg = xmlStrcat(msg, BAD_CAST " [");
1716 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1717 msg = xmlStrcat(msg, BAD_CAST "]");
1718 }
1719 msg = xmlStrcat(msg, BAD_CAST ": ");
1720 } else
1721 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001722 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001723 msg = xmlStrcat(msg, BAD_CAST ".\n");
1724 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1725 FREE_AND_NULL(msg)
1726 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001727}
1728
William M. Brack2f2a6632004-08-20 23:09:47 +00001729/**
1730 * xmlSchemaWildcardPCToString:
1731 * @pc: the type of processContents
1732 *
1733 * Returns a string representation of the type of
1734 * processContents.
1735 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001736static const char *
1737xmlSchemaWildcardPCToString(int pc)
1738{
1739 switch (pc) {
1740 case XML_SCHEMAS_ANY_SKIP:
1741 return ("skip");
1742 case XML_SCHEMAS_ANY_LAX:
1743 return ("lax");
1744 case XML_SCHEMAS_ANY_STRICT:
1745 return ("strict");
1746 default:
1747 return ("invalid process contents");
1748 }
1749}
1750
William M. Brack2f2a6632004-08-20 23:09:47 +00001751/**
1752 * xmlSchemaVWildcardErr:
1753 * @ctxt: the schema validation context
1754 * @error: the error code
1755 * @node: the validated node
1756 * @wild: the wildcard used
1757 * @message: the error message
1758 *
1759 * Reports an validation-by-wildcard error.
1760 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001761static void
1762xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1763 xmlParserErrors error,
1764 xmlNodePtr node,
1765 xmlSchemaWildcardPtr wild,
1766 const char *message)
1767{
1768 xmlChar *des = NULL, *msg = NULL;
1769
1770 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1771 msg = xmlStrdup(BAD_CAST "%s, [");
1772 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001773 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001774 msg = xmlStrcat(msg, (const xmlChar *) message);
1775 msg = xmlStrcat(msg, BAD_CAST ".\n");
1776 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1777 FREE_AND_NULL(des);
1778 FREE_AND_NULL(msg);
1779}
1780
1781/**
1782 * xmlSchemaVMissingAttrErr:
1783 * @ctxt: the schema validation context
1784 * @node: the parent element node of the missing attribute node
1785 * @type: the corresponding type of the attribute node
1786 *
1787 * Reports an illegal attribute.
1788 */
1789static void
1790xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1791 xmlNodePtr elem,
1792 xmlSchemaAttributePtr type)
1793{
1794 const xmlChar *name, *uri;
1795 xmlChar *strE = NULL, *strA = NULL;
1796
1797 if (type->ref != NULL) {
1798 name = type->ref;
1799 uri = type->refNs;
1800 } else {
1801 name = type->name;
1802 uri = type->targetNamespace;
1803 }
1804 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001805 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1806 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001807 "%s: The attribute %s is required but missing.\n",
1808 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1809 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1810 FREE_AND_NULL(strE)
1811 FREE_AND_NULL(strA)
1812}
1813
Daniel Veillard4255d502002-04-16 15:50:10 +00001814/************************************************************************
1815 * *
1816 * Allocation functions *
1817 * *
1818 ************************************************************************/
1819
1820/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001821 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001822 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001823 *
1824 * Allocate a new Schema structure.
1825 *
1826 * Returns the newly allocated structure or NULL in case or error
1827 */
1828static xmlSchemaPtr
1829xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1830{
1831 xmlSchemaPtr ret;
1832
1833 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1834 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001835 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001836 return (NULL);
1837 }
1838 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001839 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001840 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001841
1842 return (ret);
1843}
1844
1845/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001846 * xmlSchemaNewSchema:
1847 * @ctxt: a schema validation context
1848 *
1849 * Allocate a new Schema structure.
1850 *
1851 * Returns the newly allocated structure or NULL in case or error
1852 */
1853static xmlSchemaAssemblePtr
1854xmlSchemaNewAssemble(void)
1855{
1856 xmlSchemaAssemblePtr ret;
1857
1858 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1859 if (ret == NULL) {
1860 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1861 return (NULL);
1862 }
1863 memset(ret, 0, sizeof(xmlSchemaAssemble));
1864 ret->items = NULL;
1865 return (ret);
1866}
1867
1868/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001869 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001870 *
1871 * Allocate a new Facet structure.
1872 *
1873 * Returns the newly allocated structure or NULL in case or error
1874 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001875xmlSchemaFacetPtr
1876xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001877{
1878 xmlSchemaFacetPtr ret;
1879
1880 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1881 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001882 return (NULL);
1883 }
1884 memset(ret, 0, sizeof(xmlSchemaFacet));
1885
1886 return (ret);
1887}
1888
1889/**
1890 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001891 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001892 * @node: a node
1893 *
1894 * Allocate a new annotation structure.
1895 *
1896 * Returns the newly allocated structure or NULL in case or error
1897 */
1898static xmlSchemaAnnotPtr
1899xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1900{
1901 xmlSchemaAnnotPtr ret;
1902
1903 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1904 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001905 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001906 return (NULL);
1907 }
1908 memset(ret, 0, sizeof(xmlSchemaAnnot));
1909 ret->content = node;
1910 return (ret);
1911}
1912
1913/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001914 * xmlSchemaFreeAnnot:
1915 * @annot: a schema type structure
1916 *
1917 * Deallocate a annotation structure
1918 */
1919static void
1920xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1921{
1922 if (annot == NULL)
1923 return;
1924 xmlFree(annot);
1925}
1926
1927/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001928 * xmlSchemaFreeImport:
1929 * @import: a schema import structure
1930 *
1931 * Deallocate an import structure
1932 */
1933static void
1934xmlSchemaFreeImport(xmlSchemaImportPtr import)
1935{
1936 if (import == NULL)
1937 return;
1938
1939 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001940 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001941 xmlFree(import);
1942}
1943
1944/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001945 * xmlSchemaFreeInclude:
1946 * @include: a schema include structure
1947 *
1948 * Deallocate an include structure
1949 */
1950static void
1951xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1952{
1953 if (include == NULL)
1954 return;
1955
1956 xmlFreeDoc(include->doc);
1957 xmlFree(include);
1958}
1959
1960/**
1961 * xmlSchemaFreeIncludeList:
1962 * @includes: a schema include list
1963 *
1964 * Deallocate an include structure
1965 */
1966static void
1967xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1968{
1969 xmlSchemaIncludePtr next;
1970
1971 while (includes != NULL) {
1972 next = includes->next;
1973 xmlSchemaFreeInclude(includes);
1974 includes = next;
1975 }
1976}
1977
1978/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001979 * xmlSchemaFreeNotation:
1980 * @schema: a schema notation structure
1981 *
1982 * Deallocate a Schema Notation structure.
1983 */
1984static void
1985xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1986{
1987 if (nota == NULL)
1988 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001989 xmlFree(nota);
1990}
1991
1992/**
1993 * xmlSchemaFreeAttribute:
1994 * @schema: a schema attribute structure
1995 *
1996 * Deallocate a Schema Attribute structure.
1997 */
1998static void
1999xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2000{
2001 if (attr == NULL)
2002 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002003 if (attr->annot != NULL)
2004 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002005 if (attr->defVal != NULL)
2006 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002007 xmlFree(attr);
2008}
2009
2010/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002011 * xmlSchemaFreeWildcardNsSet:
2012 * set: a schema wildcard namespace
2013 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002014 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002015 */
2016static void
2017xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2018{
2019 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002020
Daniel Veillard3646d642004-06-02 19:19:14 +00002021 while (set != NULL) {
2022 next = set->next;
2023 xmlFree(set);
2024 set = next;
2025 }
2026}
2027
2028/**
2029 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002030 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002031 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002032 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002033 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002034void
Daniel Veillard3646d642004-06-02 19:19:14 +00002035xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2036{
2037 if (wildcard == NULL)
2038 return;
2039 if (wildcard->annot != NULL)
2040 xmlSchemaFreeAnnot(wildcard->annot);
2041 if (wildcard->nsSet != NULL)
2042 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2043 if (wildcard->negNsSet != NULL)
2044 xmlFree(wildcard->negNsSet);
2045 xmlFree(wildcard);
2046}
2047
2048/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002049 * xmlSchemaFreeAttributeGroup:
2050 * @schema: a schema attribute group structure
2051 *
2052 * Deallocate a Schema Attribute Group structure.
2053 */
2054static void
2055xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2056{
2057 if (attr == NULL)
2058 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002059 if (attr->annot != NULL)
2060 xmlSchemaFreeAnnot(attr->annot);
2061 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2062 (attr->attributeWildcard != NULL))
2063 xmlSchemaFreeWildcard(attr->attributeWildcard);
2064
Daniel Veillard4255d502002-04-16 15:50:10 +00002065 xmlFree(attr);
2066}
2067
2068/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002069 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002070 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002071 *
2072 * Deallocate a list of schema attribute uses.
2073 */
2074static void
2075xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2076{
2077 xmlSchemaAttributeLinkPtr next;
2078
2079 while (attrUse != NULL) {
2080 next = attrUse->next;
2081 xmlFree(attrUse);
2082 attrUse = next;
2083 }
2084}
2085
2086/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002087 * xmlSchemaFreeTypeLinkList:
2088 * @alink: a type link
2089 *
2090 * Deallocate a list of types.
2091 */
2092static void
2093xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2094{
2095 xmlSchemaTypeLinkPtr next;
2096
2097 while (link != NULL) {
2098 next = link->next;
2099 xmlFree(link);
2100 link = next;
2101 }
2102}
2103
2104/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002105 * xmlSchemaFreeElement:
2106 * @schema: a schema element structure
2107 *
2108 * Deallocate a Schema Element structure.
2109 */
2110static void
2111xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2112{
2113 if (elem == NULL)
2114 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002115 if (elem->annot != NULL)
2116 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002117 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002118 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002119 if (elem->defVal != NULL)
2120 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002121 xmlFree(elem);
2122}
2123
2124/**
2125 * xmlSchemaFreeFacet:
2126 * @facet: a schema facet structure
2127 *
2128 * Deallocate a Schema Facet structure.
2129 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002130void
Daniel Veillard4255d502002-04-16 15:50:10 +00002131xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2132{
2133 if (facet == NULL)
2134 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002135 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002136 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002137 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002138 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002139 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002140 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002141 xmlFree(facet);
2142}
2143
2144/**
2145 * xmlSchemaFreeType:
2146 * @type: a schema type structure
2147 *
2148 * Deallocate a Schema Type structure.
2149 */
2150void
2151xmlSchemaFreeType(xmlSchemaTypePtr type)
2152{
2153 if (type == NULL)
2154 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002155 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002156 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002157 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002158 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002159
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002160 facet = type->facets;
2161 while (facet != NULL) {
2162 next = facet->next;
2163 xmlSchemaFreeFacet(facet);
2164 facet = next;
2165 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002166 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002167 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2168 if (type->attributeUses != NULL)
2169 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002170 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002171 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002172 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2173 /*
2174 * NOTE: The only case where an attribute wildcard
2175 * is not owned, is if a complex type inherits it
2176 * from a base type.
2177 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002178 xmlSchemaFreeWildcard(type->attributeWildcard);
2179 }
2180 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002181 if (type->memberTypes != NULL)
2182 xmlSchemaFreeTypeLinkList(type->memberTypes);
2183 if (type->facetSet != NULL) {
2184 xmlSchemaFacetLinkPtr next, link;
2185
2186 link = type->facetSet;
2187 do {
2188 next = link->next;
2189 xmlFree(link);
2190 link = next;
2191 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002192 }
2193 if (type->contModel != NULL)
2194 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002195 xmlFree(type);
2196}
2197
2198/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002199 * xmlSchemaFreeTypeList:
2200 * @type: a schema type structure
2201 *
2202 * Deallocate a Schema Type structure.
2203 */
2204static void
2205xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2206{
2207 xmlSchemaTypePtr next;
2208
2209 while (type != NULL) {
2210 next = type->redef;
2211 xmlSchemaFreeType(type);
2212 type = next;
2213 }
2214}
2215
2216/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 * xmlSchemaFree:
2218 * @schema: a schema structure
2219 *
2220 * Deallocate a Schema structure.
2221 */
2222void
2223xmlSchemaFree(xmlSchemaPtr schema)
2224{
2225 if (schema == NULL)
2226 return;
2227
Daniel Veillard4255d502002-04-16 15:50:10 +00002228 if (schema->notaDecl != NULL)
2229 xmlHashFree(schema->notaDecl,
2230 (xmlHashDeallocator) xmlSchemaFreeNotation);
2231 if (schema->attrDecl != NULL)
2232 xmlHashFree(schema->attrDecl,
2233 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2234 if (schema->attrgrpDecl != NULL)
2235 xmlHashFree(schema->attrgrpDecl,
2236 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2237 if (schema->elemDecl != NULL)
2238 xmlHashFree(schema->elemDecl,
2239 (xmlHashDeallocator) xmlSchemaFreeElement);
2240 if (schema->typeDecl != NULL)
2241 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002242 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002243 if (schema->groupDecl != NULL)
2244 xmlHashFree(schema->groupDecl,
2245 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002246 if (schema->schemasImports != NULL)
2247 xmlHashFree(schema->schemasImports,
2248 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002249 if (schema->includes != NULL) {
2250 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2251 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002252 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002254 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002255 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002256 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002257 xmlFree(schema);
2258}
2259
2260/************************************************************************
2261 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002262 * Debug functions *
2263 * *
2264 ************************************************************************/
2265
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002266#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002267
Daniel Veillard4255d502002-04-16 15:50:10 +00002268/**
2269 * xmlSchemaElementDump:
2270 * @elem: an element
2271 * @output: the file output
2272 *
2273 * Dump the element
2274 */
2275static void
2276xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002277 const xmlChar * name ATTRIBUTE_UNUSED,
2278 const xmlChar * context ATTRIBUTE_UNUSED,
2279 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002280{
2281 if (elem == NULL)
2282 return;
2283
2284 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002285 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2286 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002287 fprintf(output, ": %s ", elem->name);
2288 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002289 fprintf(output, "namespace '%s' ", namespace);
2290
Daniel Veillard4255d502002-04-16 15:50:10 +00002291 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002292 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002293 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002294 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002295 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002296 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002297 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002298 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002299 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002300 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002301 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002302 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002303 fprintf(output, "\n");
2304 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002305 fprintf(output, " ");
2306 if (elem->minOccurs != 1)
2307 fprintf(output, "min: %d ", elem->minOccurs);
2308 if (elem->maxOccurs >= UNBOUNDED)
2309 fprintf(output, "max: unbounded\n");
2310 else if (elem->maxOccurs != 1)
2311 fprintf(output, "max: %d\n", elem->maxOccurs);
2312 else
2313 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002314 }
2315 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002316 fprintf(output, " type: %s", elem->namedType);
2317 if (elem->namedTypeNs != NULL)
2318 fprintf(output, " ns %s\n", elem->namedTypeNs);
2319 else
2320 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002321 }
2322 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002323 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2324 if (elem->substGroupNs != NULL)
2325 fprintf(output, " ns %s\n", elem->substGroupNs);
2326 else
2327 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002328 }
2329 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002330 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002331}
2332
2333/**
2334 * xmlSchemaAnnotDump:
2335 * @output: the file output
2336 * @annot: a annotation
2337 *
2338 * Dump the annotation
2339 */
2340static void
2341xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2342{
2343 xmlChar *content;
2344
2345 if (annot == NULL)
2346 return;
2347
2348 content = xmlNodeGetContent(annot->content);
2349 if (content != NULL) {
2350 fprintf(output, " Annot: %s\n", content);
2351 xmlFree(content);
2352 } else
2353 fprintf(output, " Annot: empty\n");
2354}
2355
2356/**
2357 * xmlSchemaTypeDump:
2358 * @output: the file output
2359 * @type: a type structure
2360 *
2361 * Dump a SchemaType structure
2362 */
2363static void
2364xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2365{
2366 if (type == NULL) {
2367 fprintf(output, "Type: NULL\n");
2368 return;
2369 }
2370 fprintf(output, "Type: ");
2371 if (type->name != NULL)
2372 fprintf(output, "%s, ", type->name);
2373 else
2374 fprintf(output, "no name");
2375 switch (type->type) {
2376 case XML_SCHEMA_TYPE_BASIC:
2377 fprintf(output, "basic ");
2378 break;
2379 case XML_SCHEMA_TYPE_SIMPLE:
2380 fprintf(output, "simple ");
2381 break;
2382 case XML_SCHEMA_TYPE_COMPLEX:
2383 fprintf(output, "complex ");
2384 break;
2385 case XML_SCHEMA_TYPE_SEQUENCE:
2386 fprintf(output, "sequence ");
2387 break;
2388 case XML_SCHEMA_TYPE_CHOICE:
2389 fprintf(output, "choice ");
2390 break;
2391 case XML_SCHEMA_TYPE_ALL:
2392 fprintf(output, "all ");
2393 break;
2394 case XML_SCHEMA_TYPE_UR:
2395 fprintf(output, "ur ");
2396 break;
2397 case XML_SCHEMA_TYPE_RESTRICTION:
2398 fprintf(output, "restriction ");
2399 break;
2400 case XML_SCHEMA_TYPE_EXTENSION:
2401 fprintf(output, "extension ");
2402 break;
2403 default:
2404 fprintf(output, "unknowntype%d ", type->type);
2405 break;
2406 }
2407 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002408 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002409 }
2410 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002411 case XML_SCHEMA_CONTENT_UNKNOWN:
2412 fprintf(output, "unknown ");
2413 break;
2414 case XML_SCHEMA_CONTENT_EMPTY:
2415 fprintf(output, "empty ");
2416 break;
2417 case XML_SCHEMA_CONTENT_ELEMENTS:
2418 fprintf(output, "element ");
2419 break;
2420 case XML_SCHEMA_CONTENT_MIXED:
2421 fprintf(output, "mixed ");
2422 break;
2423 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002424 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002425 break;
2426 case XML_SCHEMA_CONTENT_BASIC:
2427 fprintf(output, "basic ");
2428 break;
2429 case XML_SCHEMA_CONTENT_SIMPLE:
2430 fprintf(output, "simple ");
2431 break;
2432 case XML_SCHEMA_CONTENT_ANY:
2433 fprintf(output, "any ");
2434 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002435 }
2436 fprintf(output, "\n");
2437 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002438 fprintf(output, " ");
2439 if (type->minOccurs != 1)
2440 fprintf(output, "min: %d ", type->minOccurs);
2441 if (type->maxOccurs >= UNBOUNDED)
2442 fprintf(output, "max: unbounded\n");
2443 else if (type->maxOccurs != 1)
2444 fprintf(output, "max: %d\n", type->maxOccurs);
2445 else
2446 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002447 }
2448 if (type->annot != NULL)
2449 xmlSchemaAnnotDump(output, type->annot);
2450 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002451 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002452
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002453 fprintf(output, " subtypes: ");
2454 while (sub != NULL) {
2455 fprintf(output, "%s ", sub->name);
2456 sub = sub->next;
2457 }
2458 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002459 }
2460
2461}
2462
2463/**
2464 * xmlSchemaDump:
2465 * @output: the file output
2466 * @schema: a schema structure
2467 *
2468 * Dump a Schema structure.
2469 */
2470void
2471xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2472{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002473 if (output == NULL)
2474 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002475 if (schema == NULL) {
2476 fprintf(output, "Schemas: NULL\n");
2477 return;
2478 }
2479 fprintf(output, "Schemas: ");
2480 if (schema->name != NULL)
2481 fprintf(output, "%s, ", schema->name);
2482 else
2483 fprintf(output, "no name, ");
2484 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002485 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002486 else
2487 fprintf(output, "no target namespace");
2488 fprintf(output, "\n");
2489 if (schema->annot != NULL)
2490 xmlSchemaAnnotDump(output, schema->annot);
2491
2492 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2493 output);
2494 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002495 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002496}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002497#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002498
2499/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002500 * *
2501 * Utilities *
2502 * *
2503 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002504
Daniel Veillardc0826a72004-08-10 14:17:33 +00002505/**
2506 * xmlSchemaGetPropNode:
2507 * @node: the element node
2508 * @name: the name of the attribute
2509 *
2510 * Seeks an attribute with a name of @name in
2511 * no namespace.
2512 *
2513 * Returns the attribute or NULL if not present.
2514 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002515static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002516xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002517{
2518 xmlAttrPtr prop;
2519
Daniel Veillardc0826a72004-08-10 14:17:33 +00002520 if ((node == NULL) || (name == NULL))
2521 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002522 prop = node->properties;
2523 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002524 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2525 return(prop);
2526 prop = prop->next;
2527 }
2528 return (NULL);
2529}
2530
2531/**
2532 * xmlSchemaGetPropNodeNs:
2533 * @node: the element node
2534 * @uri: the uri
2535 * @name: the name of the attribute
2536 *
2537 * Seeks an attribute with a local name of @name and
2538 * a namespace URI of @uri.
2539 *
2540 * Returns the attribute or NULL if not present.
2541 */
2542static xmlAttrPtr
2543xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2544{
2545 xmlAttrPtr prop;
2546
2547 if ((node == NULL) || (name == NULL))
2548 return(NULL);
2549 prop = node->properties;
2550 while (prop != NULL) {
2551 if ((prop->ns != NULL) &&
2552 xmlStrEqual(prop->name, BAD_CAST name) &&
2553 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002554 return(prop);
2555 prop = prop->next;
2556 }
2557 return (NULL);
2558}
2559
2560static const xmlChar *
2561xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2562{
2563 xmlChar *val;
2564 const xmlChar *ret;
2565
2566 val = xmlNodeGetContent(node);
2567 if (val == NULL)
2568 return(NULL);
2569 ret = xmlDictLookup(ctxt->dict, val, -1);
2570 xmlFree(val);
2571 return(ret);
2572}
2573
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002574/**
2575 * xmlSchemaGetProp:
2576 * @ctxt: the parser context
2577 * @node: the node
2578 * @name: the property name
2579 *
2580 * Read a attribute value and internalize the string
2581 *
2582 * Returns the string or NULL if not present.
2583 */
2584static const xmlChar *
2585xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2586 const char *name)
2587{
2588 xmlChar *val;
2589 const xmlChar *ret;
2590
2591 val = xmlGetProp(node, BAD_CAST name);
2592 if (val == NULL)
2593 return(NULL);
2594 ret = xmlDictLookup(ctxt->dict, val, -1);
2595 xmlFree(val);
2596 return(ret);
2597}
2598
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002599/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002600 * *
2601 * Parsing functions *
2602 * *
2603 ************************************************************************/
2604
2605/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002606 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002607 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002608 * @name: the element name
2609 * @ns: the element namespace
2610 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002611 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002612 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002613 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002614 */
2615static xmlSchemaElementPtr
2616xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002617 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002618{
2619 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002620
2621 if ((name == NULL) || (schema == NULL))
2622 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002623
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002624 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002625 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002626 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002627 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002628 } else
2629 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002630 /*
2631 * This one was removed, since top level element declarations have
2632 * the target namespace specified in targetNamespace of the <schema>
2633 * information element, even if elementFormDefault is "unqualified".
2634 */
2635
2636 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002637 if (xmlStrEqual(namespace, schema->targetNamespace))
2638 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2639 else
2640 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002641 if ((ret != NULL) &&
2642 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002643 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002644 }
William M. Bracke7091952004-05-11 15:09:58 +00002645 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002646
William M. Brack2f2a6632004-08-20 23:09:47 +00002647 /*
2648 * Removed since imported components will be hold by the main schema only.
2649 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002650 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002651 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002652 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002653 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002654 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002655 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002656 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2657 return (ret);
2658 } else
2659 ret = NULL;
2660 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002661 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002662#ifdef DEBUG
2663 if (ret == NULL) {
2664 if (namespace == NULL)
2665 fprintf(stderr, "Unable to lookup type %s", name);
2666 else
2667 fprintf(stderr, "Unable to lookup type %s:%s", name,
2668 namespace);
2669 }
2670#endif
2671 return (ret);
2672}
2673
2674/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002675 * xmlSchemaGetType:
2676 * @schema: the schemas context
2677 * @name: the type name
2678 * @ns: the type namespace
2679 *
2680 * Lookup a type in the schemas or the predefined types
2681 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002682 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002683 */
2684static xmlSchemaTypePtr
2685xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 const xmlChar * namespace)
2687{
Daniel Veillard4255d502002-04-16 15:50:10 +00002688 xmlSchemaTypePtr ret;
2689
2690 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002691 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002693 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002694 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002695 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002696 }
2697 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002698 if (ret != NULL)
2699 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002700 /*
2701 * Removed, since the imported components will be grafted on the
2702 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002703 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002704 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002705 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002706 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002707 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002708 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002709 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2710 return (ret);
2711 } else
2712 ret = NULL;
2713 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002714 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002715#ifdef DEBUG
2716 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002717 if (namespace == NULL)
2718 fprintf(stderr, "Unable to lookup type %s", name);
2719 else
2720 fprintf(stderr, "Unable to lookup type %s:%s", name,
2721 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002722 }
2723#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002724 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002725}
2726
Daniel Veillard3646d642004-06-02 19:19:14 +00002727/**
2728 * xmlSchemaGetAttribute:
2729 * @schema: the context of the schema
2730 * @name: the name of the attribute
2731 * @ns: the target namespace of the attribute
2732 *
2733 * Lookup a an attribute in the schema or imported schemas
2734 *
2735 * Returns the attribute declaration or NULL if not found.
2736 */
2737static xmlSchemaAttributePtr
2738xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2739 const xmlChar * namespace)
2740{
2741 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002742
2743 if ((name == NULL) || (schema == NULL))
2744 return (NULL);
2745
2746
2747 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2748 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2749 return (ret);
2750 else
2751 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002752 /*
2753 * Removed, since imported components will be hold by the main schema only.
2754 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002755 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002756 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002757 else
2758 import = xmlHashLookup(schema->schemasImports, namespace);
2759 if (import != NULL) {
2760 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2761 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2762 return (ret);
2763 } else
2764 ret = NULL;
2765 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002766 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002767#ifdef DEBUG
2768 if (ret == NULL) {
2769 if (namespace == NULL)
2770 fprintf(stderr, "Unable to lookup attribute %s", name);
2771 else
2772 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2773 namespace);
2774 }
2775#endif
2776 return (ret);
2777}
2778
2779/**
2780 * xmlSchemaGetAttributeGroup:
2781 * @schema: the context of the schema
2782 * @name: the name of the attribute group
2783 * @ns: the target namespace of the attribute group
2784 *
2785 * Lookup a an attribute group in the schema or imported schemas
2786 *
2787 * Returns the attribute group definition or NULL if not found.
2788 */
2789static xmlSchemaAttributeGroupPtr
2790xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2791 const xmlChar * namespace)
2792{
2793 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002794
2795 if ((name == NULL) || (schema == NULL))
2796 return (NULL);
2797
2798
2799 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2800 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2801 return (ret);
2802 else
2803 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002804 /*
2805 * Removed since imported components will be hold by the main schema only.
2806 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002807 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002808 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002809 else
2810 import = xmlHashLookup(schema->schemasImports, namespace);
2811 if (import != NULL) {
2812 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2813 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2814 return (ret);
2815 else
2816 ret = NULL;
2817 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002818 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002819#ifdef DEBUG
2820 if (ret == NULL) {
2821 if (namespace == NULL)
2822 fprintf(stderr, "Unable to lookup attribute group %s", name);
2823 else
2824 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2825 namespace);
2826 }
2827#endif
2828 return (ret);
2829}
2830
2831/**
2832 * xmlSchemaGetGroup:
2833 * @schema: the context of the schema
2834 * @name: the name of the group
2835 * @ns: the target namespace of the group
2836 *
2837 * Lookup a group in the schema or imported schemas
2838 *
2839 * Returns the group definition or NULL if not found.
2840 */
2841static xmlSchemaTypePtr
2842xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2843 const xmlChar * namespace)
2844{
2845 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002846
2847 if ((name == NULL) || (schema == NULL))
2848 return (NULL);
2849
2850
2851 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2852 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2853 return (ret);
2854 else
2855 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002856 /*
2857 * Removed since imported components will be hold by the main schema only.
2858 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002859 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002860 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002861 else
2862 import = xmlHashLookup(schema->schemasImports, namespace);
2863 if (import != NULL) {
2864 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2865 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2866 return (ret);
2867 else
2868 ret = NULL;
2869 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002870 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002871#ifdef DEBUG
2872 if (ret == NULL) {
2873 if (namespace == NULL)
2874 fprintf(stderr, "Unable to lookup group %s", name);
2875 else
2876 fprintf(stderr, "Unable to lookup group %s:%s", name,
2877 namespace);
2878 }
2879#endif
2880 return (ret);
2881}
2882
Daniel Veillard4255d502002-04-16 15:50:10 +00002883/************************************************************************
2884 * *
2885 * Parsing functions *
2886 * *
2887 ************************************************************************/
2888
2889#define IS_BLANK_NODE(n) \
2890 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2891
2892/**
2893 * xmlSchemaIsBlank:
2894 * @str: a string
2895 *
2896 * Check if a string is ignorable
2897 *
2898 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2899 */
2900static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002901xmlSchemaIsBlank(xmlChar * str)
2902{
Daniel Veillard4255d502002-04-16 15:50:10 +00002903 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002904 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002905 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002906 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002907 return (0);
2908 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002909 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002910 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002911}
2912
2913/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002914 * xmlSchemaAddAssembledItem:
2915 * @ctxt: a schema parser context
2916 * @schema: the schema being built
2917 * @item: the item
2918 *
2919 * Add a item to the schema's list of current items.
2920 * This is used if the schema was already constructed and
2921 * new schemata need to be added to it.
2922 * *WARNING* this interface is highly subject to change.
2923 *
2924 * Returns 0 if suceeds and -1 if an internal error occurs.
2925 */
2926static int
2927xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
2928 xmlSchemaTypePtr item)
2929{
2930 static int growSize = 100;
2931 xmlSchemaAssemblePtr ass;
2932
2933 ass = ctxt->assemble;
2934 if (ass->sizeItems < 0) {
2935 /* If disabled. */
2936 return (0);
2937 }
2938 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002939 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002940 if (ass->items == NULL) {
2941 xmlSchemaPErrMemory(ctxt,
2942 "allocating new item buffer", NULL);
2943 return (-1);
2944 }
2945 ass->sizeItems = growSize;
2946 } else if (ass->sizeItems <= ass->nbItems) {
2947 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002948 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002949 ass->sizeItems * sizeof(xmlSchemaTypePtr));
2950 if (ass->items == NULL) {
2951 xmlSchemaPErrMemory(ctxt,
2952 "growing item buffer", NULL);
2953 ass->sizeItems = 0;
2954 return (-1);
2955 }
2956 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002957 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002958 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
2959 return (0);
2960}
2961
2962/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002963 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002964 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002965 * @schema: the schema being built
2966 * @name: the item name
2967 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002968 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002969 * *WARNING* this interface is highly subject to change
2970 *
2971 * Returns the new struture or NULL in case of error
2972 */
2973static xmlSchemaNotationPtr
2974xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002975 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002976{
2977 xmlSchemaNotationPtr ret = NULL;
2978 int val;
2979
2980 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2981 return (NULL);
2982
2983 if (schema->notaDecl == NULL)
2984 schema->notaDecl = xmlHashCreate(10);
2985 if (schema->notaDecl == NULL)
2986 return (NULL);
2987
2988 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2989 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002990 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002991 return (NULL);
2992 }
2993 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002994 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002995 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2996 ret);
2997 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002998 /*
2999 * TODO: This should never happen, since a unique name will be computed.
3000 * If it fails, then an other internal error must have occured.
3001 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003002 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3003 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003004 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003005 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003006 xmlFree(ret);
3007 return (NULL);
3008 }
3009 return (ret);
3010}
3011
3012
3013/**
3014 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003015 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 * @schema: the schema being built
3017 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003018 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 *
3020 * Add an XML schema Attrribute declaration
3021 * *WARNING* this interface is highly subject to change
3022 *
3023 * Returns the new struture or NULL in case of error
3024 */
3025static xmlSchemaAttributePtr
3026xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003027 const xmlChar * name, const xmlChar * namespace,
3028 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003029{
3030 xmlSchemaAttributePtr ret = NULL;
3031 int val;
3032
3033 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3034 return (NULL);
3035
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003036#ifdef DEBUG
3037 fprintf(stderr, "Adding attribute %s\n", name);
3038 if (namespace != NULL)
3039 fprintf(stderr, " target namespace %s\n", namespace);
3040#endif
3041
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 if (schema->attrDecl == NULL)
3043 schema->attrDecl = xmlHashCreate(10);
3044 if (schema->attrDecl == NULL)
3045 return (NULL);
3046
3047 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3048 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003049 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003050 return (NULL);
3051 }
3052 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003053 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3054 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003055 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003056 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003057 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003058 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003059 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003060 NULL, NULL, node,
3061 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003062 xmlFree(ret);
3063 return (NULL);
3064 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003065 if (ctxt->assemble != NULL)
3066 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003067 return (ret);
3068}
3069
3070/**
3071 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003072 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003073 * @schema: the schema being built
3074 * @name: the item name
3075 *
3076 * Add an XML schema Attrribute Group declaration
3077 *
3078 * Returns the new struture or NULL in case of error
3079 */
3080static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003081xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003082 xmlSchemaPtr schema, const xmlChar * name,
3083 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003084{
3085 xmlSchemaAttributeGroupPtr ret = NULL;
3086 int val;
3087
3088 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3089 return (NULL);
3090
3091 if (schema->attrgrpDecl == NULL)
3092 schema->attrgrpDecl = xmlHashCreate(10);
3093 if (schema->attrgrpDecl == NULL)
3094 return (NULL);
3095
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003096 ret =
3097 (xmlSchemaAttributeGroupPtr)
3098 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003099 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003100 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003101 return (NULL);
3102 }
3103 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003104 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003105 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003106 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003107 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003108 xmlSchemaPCustomErr(ctxt,
3109 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3110 NULL, NULL, node,
3111 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003112 xmlFree(ret);
3113 return (NULL);
3114 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003115 if (ctxt->assemble != NULL)
3116 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003117 return (ret);
3118}
3119
3120/**
3121 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003122 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003123 * @schema: the schema being built
3124 * @name: the type name
3125 * @namespace: the type namespace
3126 *
3127 * Add an XML schema Element declaration
3128 * *WARNING* this interface is highly subject to change
3129 *
3130 * Returns the new struture or NULL in case of error
3131 */
3132static xmlSchemaElementPtr
3133xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003134 const xmlChar * name, const xmlChar * namespace,
3135 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003136{
3137 xmlSchemaElementPtr ret = NULL;
3138 int val;
3139
3140 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3141 return (NULL);
3142
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003143#ifdef DEBUG
3144 fprintf(stderr, "Adding element %s\n", name);
3145 if (namespace != NULL)
3146 fprintf(stderr, " target namespace %s\n", namespace);
3147#endif
3148
Daniel Veillard4255d502002-04-16 15:50:10 +00003149 if (schema->elemDecl == NULL)
3150 schema->elemDecl = xmlHashCreate(10);
3151 if (schema->elemDecl == NULL)
3152 return (NULL);
3153
3154 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3155 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003156 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003157 return (NULL);
3158 }
3159 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003160 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3161 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003162 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003163 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003164 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003165 if (topLevel) {
3166 xmlSchemaPCustomErr(ctxt,
3167 XML_SCHEMAP_REDEFINED_ELEMENT,
3168 NULL, NULL, node,
3169 "A global element declaration with the name '%s' does "
3170 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003171 xmlFree(ret);
3172 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003173 } else {
3174 char buf[30];
3175
3176 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3177 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3178 namespace, ret);
3179 if (val != 0) {
3180 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003181 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003182 NULL, NULL, node,
3183 "Internal error: xmlSchemaAddElement, "
3184 "a dublicate element declaration with the name '%s' "
3185 "could not be added to the hash.", name);
3186 xmlFree(ret);
3187 return (NULL);
3188 }
3189 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003190
Daniel Veillard4255d502002-04-16 15:50:10 +00003191 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003192 if (ctxt->assemble != NULL)
3193 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 return (ret);
3195}
3196
3197/**
3198 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003199 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 * @schema: the schema being built
3201 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003202 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003203 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003204 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003205 * *WARNING* this interface is highly subject to change
3206 *
3207 * Returns the new struture or NULL in case of error
3208 */
3209static xmlSchemaTypePtr
3210xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003211 const xmlChar * name, const xmlChar * namespace,
3212 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003213{
3214 xmlSchemaTypePtr ret = NULL;
3215 int val;
3216
3217 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3218 return (NULL);
3219
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003220#ifdef DEBUG
3221 fprintf(stderr, "Adding type %s\n", name);
3222 if (namespace != NULL)
3223 fprintf(stderr, " target namespace %s\n", namespace);
3224#endif
3225
Daniel Veillard4255d502002-04-16 15:50:10 +00003226 if (schema->typeDecl == NULL)
3227 schema->typeDecl = xmlHashCreate(10);
3228 if (schema->typeDecl == NULL)
3229 return (NULL);
3230
3231 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3232 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003233 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003234 return (NULL);
3235 }
3236 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003237 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003238 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003239 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003240 if (val != 0) {
3241 if (ctxt->includes == 0) {
3242 xmlSchemaPCustomErr(ctxt,
3243 XML_SCHEMAP_REDEFINED_TYPE,
3244 NULL, NULL, node,
3245 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003246 xmlFree(ret);
3247 return (NULL);
3248 } else {
3249 xmlSchemaTypePtr prev;
3250
3251 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3252 if (prev == NULL) {
3253 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003254 XML_ERR_INTERNAL_ERROR,
3255 "Internal error: xmlSchemaAddType, on type "
3256 "'%s'.\n",
3257 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003258 xmlFree(ret);
3259 return (NULL);
3260 }
3261 ret->redef = prev->redef;
3262 prev->redef = ret;
3263 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003264 }
3265 ret->minOccurs = 1;
3266 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003267 ret->attributeUses = NULL;
3268 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003269 if (ctxt->assemble != NULL)
3270 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003271 return (ret);
3272}
3273
3274/**
3275 * xmlSchemaAddGroup:
3276 * @ctxt: a schema validation context
3277 * @schema: the schema being built
3278 * @name: the group name
3279 *
3280 * Add an XML schema Group definition
3281 *
3282 * Returns the new struture or NULL in case of error
3283 */
3284static xmlSchemaTypePtr
3285xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003286 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003287{
3288 xmlSchemaTypePtr ret = NULL;
3289 int val;
3290
3291 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3292 return (NULL);
3293
3294 if (schema->groupDecl == NULL)
3295 schema->groupDecl = xmlHashCreate(10);
3296 if (schema->groupDecl == NULL)
3297 return (NULL);
3298
3299 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3300 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003301 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003302 return (NULL);
3303 }
3304 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003305 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003306 val =
3307 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3308 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003309 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003310 xmlSchemaPCustomErr(ctxt,
3311 XML_SCHEMAP_REDEFINED_GROUP,
3312 NULL, NULL, node,
3313 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003314 xmlFree(ret);
3315 return (NULL);
3316 }
3317 ret->minOccurs = 1;
3318 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003319 if (ctxt->assemble != NULL)
3320 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003321 return (ret);
3322}
3323
Daniel Veillard3646d642004-06-02 19:19:14 +00003324/**
3325 * xmlSchemaNewWildcardNs:
3326 * @ctxt: a schema validation context
3327 *
3328 * Creates a new wildcard namespace constraint.
3329 *
3330 * Returns the new struture or NULL in case of error
3331 */
3332static xmlSchemaWildcardNsPtr
3333xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3334{
3335 xmlSchemaWildcardNsPtr ret;
3336
3337 ret = (xmlSchemaWildcardNsPtr)
3338 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3339 if (ret == NULL) {
3340 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3341 return (NULL);
3342 }
3343 ret->value = NULL;
3344 ret->next = NULL;
3345 return (ret);
3346}
3347
3348/**
3349 * xmlSchemaAddWildcard:
3350 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003351 * Adds a wildcard. It corresponds to a
3352 * xsd:anyAttribute and is used as storage for namespace
3353 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003354 *
3355 * Returns the new struture or NULL in case of error
3356 */
3357static xmlSchemaWildcardPtr
3358xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3359{
3360 xmlSchemaWildcardPtr ret = NULL;
3361
3362 if (ctxt == NULL)
3363 return (NULL);
3364
3365 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3366 if (ret == NULL) {
3367 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3368 return (NULL);
3369 }
3370 memset(ret, 0, sizeof(xmlSchemaWildcard));
3371 ret->minOccurs = 1;
3372 ret->maxOccurs = 1;
3373
3374 return (ret);
3375}
3376
Daniel Veillard4255d502002-04-16 15:50:10 +00003377/************************************************************************
3378 * *
3379 * Utilities for parsing *
3380 * *
3381 ************************************************************************/
3382
3383/**
3384 * xmlGetQNameProp:
3385 * @ctxt: a schema validation context
3386 * @node: a subtree containing XML Schema informations
3387 * @name: the attribute name
3388 * @namespace: the result namespace if any
3389 *
3390 * Extract a QName Attribute value
3391 *
3392 * Returns the NCName or NULL if not found, and also update @namespace
3393 * with the namespace URI
3394 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003395static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003396xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003397 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003398{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003399 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003400 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003401 const xmlChar *ret, *prefix;
3402 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003403 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003404
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003405 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003406 attr = xmlSchemaGetPropNode(node, name);
3407 if (attr == NULL)
3408 return (NULL);
3409 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003410
Daniel Veillard4255d502002-04-16 15:50:10 +00003411 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003413
Daniel Veillardba0153a2004-04-01 10:42:31 +00003414 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003415 ns = xmlSearchNs(node->doc, node, 0);
3416 if (ns) {
3417 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3418 return (val);
3419 }
3420 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003421 ret = xmlSplitQName3(val, &len);
3422 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003424 }
3425 ret = xmlDictLookup(ctxt->dict, ret, -1);
3426 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003427
3428 ns = xmlSearchNs(node->doc, node, prefix);
3429 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003430 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3431 NULL, NULL, (xmlNodePtr) attr,
3432 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003433 "The QName value '%s' has no corresponding namespace "
3434 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003435 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003436 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003437 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003438 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003439}
3440
3441/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003442 * xmlSchemaPValAttrNodeQNameValue:
3443 * @ctxt: a schema parser context
3444 * @schema: the schema context
3445 * @ownerDes: the designation of the parent element
3446 * @ownerItem: the parent as a schema object
3447 * @value: the QName value
3448 * @local: the resulting local part if found, the attribute value otherwise
3449 * @uri: the resulting namespace URI if found
3450 *
3451 * Extracts the local name and the URI of a QName value and validates it.
3452 * This one is intended to be used on attribute values that
3453 * should resolve to schema components.
3454 *
3455 * Returns 0, in case the QName is valid, a positive error code
3456 * if not valid and -1 if an internal error occurs.
3457 */
3458static int
3459xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3460 xmlSchemaPtr schema,
3461 xmlChar **ownerDes,
3462 xmlSchemaTypePtr ownerItem,
3463 xmlAttrPtr attr,
3464 const xmlChar *value,
3465 const xmlChar **uri,
3466 const xmlChar **prefix,
3467 const xmlChar **local)
3468{
3469 const xmlChar *pref;
3470 xmlNsPtr ns;
3471 int len, ret;
3472
3473 *uri = NULL;
3474 *local = NULL;
3475 if (prefix != 0)
3476 *prefix = NULL;
3477 ret = xmlValidateQName(value, 1);
3478 if (ret > 0) {
3479 xmlSchemaPSimpleTypeErr(ctxt,
3480 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3481 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003482 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3483 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003484 NULL, NULL, NULL);
3485 *local = value;
3486 return (ctxt->err);
3487 } else if (ret < 0)
3488 return (-1);
3489
3490 if (!strchr((char *) value, ':')) {
3491 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3492 if (ns)
3493 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3494 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3495 /*
3496 * This one takes care of included schemas with no
3497 * target namespace.
3498 */
3499 *uri = schema->targetNamespace;
3500 }
3501 *local = value;
3502 return (0);
3503 }
3504 /*
3505 * At this point xmlSplitQName3 has to return a local name.
3506 */
3507 *local = xmlSplitQName3(value, &len);
3508 *local = xmlDictLookup(ctxt->dict, *local, -1);
3509 pref = xmlDictLookup(ctxt->dict, value, len);
3510 if (prefix != 0)
3511 *prefix = pref;
3512 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3513 if (ns == NULL) {
3514 xmlSchemaPSimpleTypeErr(ctxt,
3515 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3516 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003517 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3518 "The QName value '%s' has no corresponding namespace "
3519 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003520 return (ctxt->err);
3521 } else {
3522 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3523 }
3524 return (0);
3525}
3526
3527/**
3528 * xmlSchemaPValAttrNodeQName:
3529 * @ctxt: a schema parser context
3530 * @schema: the schema context
3531 * @ownerDes: the designation of the owner element
3532 * @ownerItem: the owner as a schema object
3533 * @attr: the attribute node
3534 * @local: the resulting local part if found, the attribute value otherwise
3535 * @uri: the resulting namespace URI if found
3536 *
3537 * Extracts and validates the QName of an attribute value.
3538 * This one is intended to be used on attribute values that
3539 * should resolve to schema components.
3540 *
3541 * Returns 0, in case the QName is valid, a positive error code
3542 * if not valid and -1 if an internal error occurs.
3543 */
3544static int
3545xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3546 xmlSchemaPtr schema,
3547 xmlChar **ownerDes,
3548 xmlSchemaTypePtr ownerItem,
3549 xmlAttrPtr attr,
3550 const xmlChar **uri,
3551 const xmlChar **prefix,
3552 const xmlChar **local)
3553{
3554 const xmlChar *value;
3555
3556 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3557 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3558 ownerDes, ownerItem, attr, value, uri, prefix, local));
3559}
3560
3561/**
3562 * xmlSchemaPValAttrQName:
3563 * @ctxt: a schema parser context
3564 * @schema: the schema context
3565 * @ownerDes: the designation of the parent element
3566 * @ownerItem: the owner as a schema object
3567 * @ownerElem: the parent node of the attribute
3568 * @name: the name of the attribute
3569 * @local: the resulting local part if found, the attribute value otherwise
3570 * @uri: the resulting namespace URI if found
3571 *
3572 * Extracts and validates the QName of an attribute value.
3573 *
3574 * Returns 0, in case the QName is valid, a positive error code
3575 * if not valid and -1 if an internal error occurs.
3576 */
3577static int
3578xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3579 xmlSchemaPtr schema,
3580 xmlChar **ownerDes,
3581 xmlSchemaTypePtr ownerItem,
3582 xmlNodePtr ownerElem,
3583 const char *name,
3584 const xmlChar **uri,
3585 const xmlChar **prefix,
3586 const xmlChar **local)
3587{
3588 xmlAttrPtr attr;
3589
3590 attr = xmlSchemaGetPropNode(ownerElem, name);
3591 if (attr == NULL) {
3592 *local = NULL;
3593 *uri = NULL;
3594 return (0);
3595 }
3596 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3597 ownerDes, ownerItem, attr, uri, prefix, local));
3598}
3599
3600/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003601 * xmlGetMaxOccurs:
3602 * @ctxt: a schema validation context
3603 * @node: a subtree containing XML Schema informations
3604 *
3605 * Get the maxOccurs property
3606 *
3607 * Returns the default if not found, or the value
3608 */
3609static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003610xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3611 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003612{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003613 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003615 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003616
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003617 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3618 if (attr == NULL)
3619 return (def);
3620 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003621
3622 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003623 if (max != UNBOUNDED) {
3624 xmlSchemaPSimpleTypeErr(ctxt,
3625 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3626 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3627 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3628 val, NULL, NULL, NULL);
3629 return (def);
3630 } else
3631 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 }
3633
3634 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003635 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003637 if (*cur == 0) {
3638 xmlSchemaPSimpleTypeErr(ctxt,
3639 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3640 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3641 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3642 val, NULL, NULL, NULL);
3643 return (def);
3644 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003646 ret = ret * 10 + (*cur - '0');
3647 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 }
William M. Brack76e95df2003-10-18 16:20:14 +00003649 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003651 /*
3652 * TODO: Restrict the maximal value to Integer.
3653 */
3654 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3655 xmlSchemaPSimpleTypeErr(ctxt,
3656 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3657 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3658 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3659 val, NULL, NULL, NULL);
3660 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003661 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003663}
3664
3665/**
3666 * xmlGetMinOccurs:
3667 * @ctxt: a schema validation context
3668 * @node: a subtree containing XML Schema informations
3669 *
3670 * Get the minOccurs property
3671 *
3672 * Returns the default if not found, or the value
3673 */
3674static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003675xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3676 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003677{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003678 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003680 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003681
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003682 attr = xmlSchemaGetPropNode(node, "minOccurs");
3683 if (attr == NULL)
3684 return (def);
3685 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003686 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003687 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003689 if (*cur == 0) {
3690 xmlSchemaPSimpleTypeErr(ctxt,
3691 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3692 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3693 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3694 val, NULL, NULL, NULL);
3695 return (def);
3696 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003697 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003698 ret = ret * 10 + (*cur - '0');
3699 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003700 }
William M. Brack76e95df2003-10-18 16:20:14 +00003701 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003702 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003703 /*
3704 * TODO: Restrict the maximal value to Integer.
3705 */
3706 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3707 xmlSchemaPSimpleTypeErr(ctxt,
3708 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3709 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3710 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3711 val, NULL, NULL, NULL);
3712 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003713 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003714 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003715}
3716
3717/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003718 * xmlSchemaPGetBoolNodeValue:
3719 * @ctxt: a schema validation context
3720 * @ownerDes: owner designation
3721 * @ownerItem: the owner as a schema item
3722 * @node: the node holding the value
3723 *
3724 * Converts a boolean string value into 1 or 0.
3725 *
3726 * Returns 0 or 1.
3727 */
3728static int
3729xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3730 xmlChar **ownerDes,
3731 xmlSchemaTypePtr ownerItem,
3732 xmlNodePtr node)
3733{
3734 xmlChar *value = NULL;
3735 int res = 0;
3736
3737 value = xmlNodeGetContent(node);
3738 /*
3739 * 3.2.2.1 Lexical representation
3740 * An instance of a datatype that is defined as ·boolean·
3741 * can have the following legal literals {true, false, 1, 0}.
3742 */
3743 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3744 res = 1;
3745 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3746 res = 0;
3747 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3748 res = 1;
3749 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3750 res = 0;
3751 else {
3752 xmlSchemaPSimpleTypeErr(ctxt,
3753 XML_SCHEMAP_INVALID_BOOLEAN,
3754 ownerDes, ownerItem, node,
3755 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3756 "(1 | 0 | true | false)", BAD_CAST value,
3757 NULL, NULL, NULL);
3758 }
3759 if (value != NULL)
3760 xmlFree(value);
3761 return (res);
3762}
3763
3764/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003765 * xmlGetBooleanProp:
3766 * @ctxt: a schema validation context
3767 * @node: a subtree containing XML Schema informations
3768 * @name: the attribute name
3769 * @def: the default value
3770 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003771 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003772 *
3773 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003774 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003775 */
3776static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003777xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3778 xmlChar **ownerDes,
3779 xmlSchemaTypePtr ownerItem,
3780 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003781 const char *name, int def)
3782{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003783 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003784
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003785 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003786 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003787 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003788 /*
3789 * 3.2.2.1 Lexical representation
3790 * An instance of a datatype that is defined as ·boolean·
3791 * can have the following legal literals {true, false, 1, 0}.
3792 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003793 if (xmlStrEqual(val, BAD_CAST "true"))
3794 def = 1;
3795 else if (xmlStrEqual(val, BAD_CAST "false"))
3796 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003797 else if (xmlStrEqual(val, BAD_CAST "1"))
3798 def = 1;
3799 else if (xmlStrEqual(val, BAD_CAST "0"))
3800 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003801 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003802 xmlSchemaPSimpleTypeErr(ctxt,
3803 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003804 ownerDes, ownerItem, node,
3805 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3806 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003808 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003809}
3810
3811/************************************************************************
3812 * *
3813 * Shema extraction from an Infoset *
3814 * *
3815 ************************************************************************/
3816static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3817 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003818 xmlNodePtr node,
3819 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003820static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3821 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003822 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003823 xmlNodePtr node,
3824 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003825static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3826 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003827 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003828 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003829static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3830 xmlSchemaPtr schema,
3831 xmlNodePtr node);
3832static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3833 xmlSchemaPtr schema,
3834 xmlNodePtr node);
3835static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3836 ctxt,
3837 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003838 xmlNodePtr node,
3839 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003840static xmlSchemaAttributeGroupPtr
3841xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003842 xmlSchemaPtr schema, xmlNodePtr node,
3843 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003844static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3845 xmlSchemaPtr schema,
3846 xmlNodePtr node);
3847static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3848 xmlSchemaPtr schema,
3849 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003850static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003851xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3852 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003853
3854/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003855 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003856 *
3857 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003858 * @ownerDes: the designation of the parent element
3859 * @ownerItem: the schema object owner if existent
3860 * @attr: the schema attribute node being validated
3861 * @value: the value
3862 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003863 *
3864 * Validates a value against the given built-in type.
3865 * This one is intended to be used internally for validation
3866 * of schema attribute values during parsing of the schema.
3867 *
3868 * Returns 0 if the value is valid, a positive error code
3869 * number otherwise and -1 in case of an internal or API error.
3870 */
3871static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003872xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3873 xmlChar **ownerDes,
3874 xmlSchemaTypePtr ownerItem,
3875 xmlAttrPtr attr,
3876 const xmlChar *value,
3877 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003878{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003879
Daniel Veillardc0826a72004-08-10 14:17:33 +00003880 int ret = 0;
3881
3882 /*
3883 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3884 * one is really meant to be used internally, so better not.
3885 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003886 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003887 return (-1);
3888 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3889 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003890 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003891 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003892 "type '%s' is not a built-in type.\n",
3893 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003894 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003895 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003896 switch (type->builtInType) {
3897 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003898 case XML_SCHEMAS_QNAME:
3899 case XML_SCHEMAS_ANYURI:
3900 case XML_SCHEMAS_TOKEN:
3901 case XML_SCHEMAS_LANGUAGE:
3902 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
3903 break;
3904
3905 /*
3906 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003907 ret = xmlValidateNCName(value, 1);
3908 break;
3909 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003910 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003911 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003912 "Internal error: xmlSchemaPvalueAttrNode, use "
3913 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3914 "for extracting QName valueues instead.\n",
3915 NULL, NULL);
3916 return (-1);
3917 case XML_SCHEMAS_ANYURI:
3918 if (value != NULL) {
3919 xmlURIPtr uri = xmlParseURI((const char *) value);
3920 if (uri == NULL)
3921 ret = 1;
3922 else
3923 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003924 }
3925 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003926 case XML_SCHEMAS_TOKEN: {
3927 const xmlChar *cur = value;
3928
3929 if (IS_BLANK_CH(*cur)) {
3930 ret = 1;
3931 } else while (*cur != 0) {
3932 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3933 ret = 1;
3934 break;
3935 } else if (*cur == ' ') {
3936 cur++;
3937 if ((*cur == 0) || (*cur == ' ')) {
3938 ret = 1;
3939 break;
3940 }
3941 } else {
3942 cur++;
3943 }
3944 }
3945 }
3946 break;
3947 case XML_SCHEMAS_LANGUAGE:
3948 if (xmlCheckLanguageID(value) != 1)
3949 ret = 1;
3950 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003951 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003952 default: {
3953 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003954 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003955 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003956 "valueidation using the type '%s' is not implemented "
3957 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003958 type->name, NULL);
3959 return (-1);
3960 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003961 }
3962 /*
3963 * TODO: Should we use the S4S error codes instead?
3964 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003965 if (ret < 0) {
3966 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3967 XML_SCHEMAP_INTERNAL,
3968 "Internal error: xmlSchemaPValAttrNodeValue, "
3969 "failed to validate a schema attribute value.\n",
3970 NULL, NULL);
3971 return (-1);
3972 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003973 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3974 xmlSchemaPSimpleTypeErr(ctxt,
3975 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3976 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003977 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003978 NULL, NULL, NULL);
3979 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3980 } else {
3981 xmlSchemaPSimpleTypeErr(ctxt,
3982 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3983 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003984 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003985 NULL, NULL, NULL);
3986 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3987 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003988 }
3989 return (ret);
3990}
3991
3992/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003993 * xmlSchemaPValAttrNode:
3994 *
3995 * @ctxt: a schema parser context
3996 * @ownerDes: the designation of the parent element
3997 * @ownerItem: the schema object owner if existent
3998 * @attr: the schema attribute node being validated
3999 * @type: the built-in type to be validated against
4000 * @value: the resulting value if any
4001 *
4002 * Extracts and validates a value against the given built-in type.
4003 * This one is intended to be used internally for validation
4004 * of schema attribute values during parsing of the schema.
4005 *
4006 * Returns 0 if the value is valid, a positive error code
4007 * number otherwise and -1 in case of an internal or API error.
4008 */
4009static int
4010xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4011 xmlChar **ownerDes,
4012 xmlSchemaTypePtr ownerItem,
4013 xmlAttrPtr attr,
4014 xmlSchemaTypePtr type,
4015 const xmlChar **value)
4016{
4017 const xmlChar *val;
4018
4019 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4020 return (-1);
4021
4022 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4023 if (value != NULL)
4024 *value = val;
4025
4026 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4027 val, type));
4028}
4029
4030/**
4031 * xmlSchemaPValAttr:
4032 *
4033 * @ctxt: a schema parser context
4034 * @node: the element node of the attribute
4035 * @ownerDes: the designation of the parent element
4036 * @ownerItem: the schema object owner if existent
4037 * @ownerElem: the owner element node
4038 * @name: the name of the schema attribute node
4039 * @type: the built-in type to be validated against
4040 * @value: the resulting value if any
4041 *
4042 * Extracts and validates a value against the given built-in type.
4043 * This one is intended to be used internally for validation
4044 * of schema attribute values during parsing of the schema.
4045 *
4046 * Returns 0 if the value is valid, a positive error code
4047 * number otherwise and -1 in case of an internal or API error.
4048 */
4049static int
4050xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4051 xmlChar **ownerDes,
4052 xmlSchemaTypePtr ownerItem,
4053 xmlNodePtr ownerElem,
4054 const char *name,
4055 xmlSchemaTypePtr type,
4056 const xmlChar **value)
4057{
4058 xmlAttrPtr attr;
4059
4060 if ((ctxt == NULL) || (type == NULL)) {
4061 if (value != NULL)
4062 *value = NULL;
4063 return (-1);
4064 }
4065 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4066 if (value != NULL)
4067 *value = NULL;
4068 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004069 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004070 "Internal error: xmlSchemaPValAttr, the given "
4071 "type '%s' is not a built-in type.\n",
4072 type->name, NULL);
4073 return (-1);
4074 }
4075 attr = xmlSchemaGetPropNode(ownerElem, name);
4076 if (attr == NULL) {
4077 if (value != NULL)
4078 *value = NULL;
4079 return (0);
4080 }
4081 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4082 type, value));
4083}
4084/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 * xmlSchemaParseAttrDecls:
4086 * @ctxt: a schema validation context
4087 * @schema: the schema being built
4088 * @node: a subtree containing XML Schema informations
4089 * @type: the hosting type
4090 *
4091 * parse a XML schema attrDecls declaration corresponding to
4092 * <!ENTITY % attrDecls
4093 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4094 */
4095static xmlNodePtr
4096xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4097 xmlNodePtr child, xmlSchemaTypePtr type)
4098{
4099 xmlSchemaAttributePtr lastattr, attr;
4100
4101 lastattr = NULL;
4102 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004103 (IS_SCHEMA(child, "attributeGroup"))) {
4104 attr = NULL;
4105 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004106 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004107 } else if (IS_SCHEMA(child, "attributeGroup")) {
4108 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004109 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004110 }
4111 if (attr != NULL) {
4112 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004113 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4114 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4115 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004116 type->attributes = attr;
4117 lastattr = attr;
4118 } else {
4119 lastattr->next = attr;
4120 lastattr = attr;
4121 }
4122 }
4123 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004124 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004125 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004126}
4127
4128/**
4129 * xmlSchemaParseAnnotation:
4130 * @ctxt: a schema validation context
4131 * @schema: the schema being built
4132 * @node: a subtree containing XML Schema informations
4133 *
4134 * parse a XML schema Attrribute declaration
4135 * *WARNING* this interface is highly subject to change
4136 *
William M. Bracke7091952004-05-11 15:09:58 +00004137 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004138 * 1 in case of success.
4139 */
4140static xmlSchemaAnnotPtr
4141xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4142 xmlNodePtr node)
4143{
4144 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004145 xmlNodePtr child = NULL;
4146 xmlAttrPtr attr;
4147 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004148
Daniel Veillardc0826a72004-08-10 14:17:33 +00004149 /*
4150 * INFO: S4S completed.
4151 */
4152 /*
4153 * id = ID
4154 * {any attributes with non-schema namespace . . .}>
4155 * Content: (appinfo | documentation)*
4156 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004157 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4158 return (NULL);
4159 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004160 attr = node->properties;
4161 while (attr != NULL) {
4162 if (((attr->ns == NULL) &&
4163 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4164 ((attr->ns != NULL) &&
4165 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4166
4167 xmlSchemaPIllegalAttrErr(ctxt,
4168 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4169 NULL, NULL, attr);
4170 }
4171 attr = attr->next;
4172 }
4173 /* TODO: Check id. */
4174
4175 /*
4176 * And now for the children...
4177 */
4178 child = node->children;
4179 while (child != NULL) {
4180 if (IS_SCHEMA(child, "appinfo")) {
4181 /* TODO: make available the content of "appinfo". */
4182 /*
4183 * source = anyURI
4184 * {any attributes with non-schema namespace . . .}>
4185 * Content: ({any})*
4186 */
4187 attr = child->properties;
4188 while (attr != NULL) {
4189 if (((attr->ns == NULL) &&
4190 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4191 ((attr->ns != NULL) &&
4192 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004193
Daniel Veillardc0826a72004-08-10 14:17:33 +00004194 xmlSchemaPIllegalAttrErr(ctxt,
4195 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4196 NULL, NULL, attr);
4197 }
4198 attr = attr->next;
4199 }
4200 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4201 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4202 child = child->next;
4203 } else if (IS_SCHEMA(child, "documentation")) {
4204 /* TODO: make available the content of "documentation". */
4205 /*
4206 * source = anyURI
4207 * {any attributes with non-schema namespace . . .}>
4208 * Content: ({any})*
4209 */
4210 attr = child->properties;
4211 while (attr != NULL) {
4212 if (attr->ns == NULL) {
4213 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4214 xmlSchemaPIllegalAttrErr(ctxt,
4215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4216 NULL, NULL, attr);
4217 }
4218 } else {
4219 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4220 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4221 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4222
4223 xmlSchemaPIllegalAttrErr(ctxt,
4224 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4225 NULL, NULL, attr);
4226 }
4227 }
4228 attr = attr->next;
4229 }
4230 /*
4231 * Attribute "xml:lang".
4232 */
4233 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4234 if (attr != NULL)
4235 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4236 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4237 child = child->next;
4238 } else {
4239 if (!barked)
4240 xmlSchemaPContentErr(ctxt,
4241 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4242 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4243 barked = 1;
4244 child = child->next;
4245 }
4246 }
4247
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 return (ret);
4249}
4250
4251/**
4252 * xmlSchemaParseFacet:
4253 * @ctxt: a schema validation context
4254 * @schema: the schema being built
4255 * @node: a subtree containing XML Schema informations
4256 *
4257 * parse a XML schema Facet declaration
4258 * *WARNING* this interface is highly subject to change
4259 *
4260 * Returns the new type structure or NULL in case of error
4261 */
4262static xmlSchemaFacetPtr
4263xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004265{
4266 xmlSchemaFacetPtr facet;
4267 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004268 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004269
4270 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4271 return (NULL);
4272
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004273 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004274 if (facet == NULL) {
4275 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4276 return (NULL);
4277 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004278 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004279 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004281 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4282 "Facet %s has no value\n", node->name, NULL);
4283 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004284 return (NULL);
4285 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004286 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004288 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004290 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004292 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004293 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004296 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004298 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004299 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004300 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004301 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004304 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004305 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4308 } else if (IS_SCHEMA(node, "minLength")) {
4309 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4310 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004311 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4312 "Unknown facet type %s\n", node->name, NULL);
4313 xmlSchemaFreeFacet(facet);
4314 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004315 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004316 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004318 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4319 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4320 const xmlChar *fixed;
4321
4322 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4323 if (fixed != NULL) {
4324 if (xmlStrEqual(fixed, BAD_CAST "true"))
4325 facet->fixed = 1;
4326 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004327 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 child = node->children;
4329
4330 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004331 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4332 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004333 }
4334 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4336 "Facet %s has unexpected child content\n",
4337 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 }
4339 return (facet);
4340}
4341
4342/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004343 * xmlSchemaParseWildcardNs:
4344 * @ctxt: a schema parser context
4345 * @wildc: the wildcard, already created
4346 * @node: a subtree containing XML Schema informations
4347 *
4348 * Parses the attribute "processContents" and "namespace"
4349 * of a xsd:anyAttribute and xsd:any.
4350 * *WARNING* this interface is highly subject to change
4351 *
4352 * Returns 0 if everything goes fine, a positive error code
4353 * if something is not valid and -1 if an internal error occurs.
4354 */
4355static int
4356xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4357 xmlSchemaPtr schema,
4358 xmlSchemaWildcardPtr wildc,
4359 xmlNodePtr node)
4360{
4361 const xmlChar *pc, *ns, *dictnsItem;
4362 int ret = 0;
4363 xmlChar *nsItem;
4364 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4365 xmlAttrPtr attr;
4366
4367 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4368 if ((pc == NULL)
4369 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4370 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4371 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4372 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4373 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4374 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4375 } else {
4376 xmlSchemaPSimpleTypeErr(ctxt,
4377 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4378 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004379 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004380 NULL, NULL, NULL);
4381 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4382 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4383 }
4384 /*
4385 * Build the namespace constraints.
4386 */
4387 attr = xmlSchemaGetPropNode(node, "namespace");
4388 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4389 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4390 wildc->any = 1;
4391 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4392 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4393 if (wildc->negNsSet == NULL) {
4394 return (-1);
4395 }
4396 wildc->negNsSet->value = schema->targetNamespace;
4397 } else {
4398 const xmlChar *end, *cur;
4399
4400 cur = ns;
4401 do {
4402 while (IS_BLANK_CH(*cur))
4403 cur++;
4404 end = cur;
4405 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4406 end++;
4407 if (end == cur)
4408 break;
4409 nsItem = xmlStrndup(cur, end - cur);
4410 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4411 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4412 xmlSchemaPSimpleTypeErr(ctxt,
4413 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4414 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004415 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004416 "((##any | ##other) | List of (anyURI | "
4417 "(##targetNamespace | ##local)))",
4418 nsItem, NULL, NULL, NULL);
4419 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4420 } else {
4421 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4422 dictnsItem = schema->targetNamespace;
4423 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4424 dictnsItem = NULL;
4425 } else {
4426 /*
4427 * Validate the item (anyURI).
4428 */
4429 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4430 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4431 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4432 }
4433 /*
4434 * Avoid dublicate namespaces.
4435 */
4436 tmp = wildc->nsSet;
4437 while (tmp != NULL) {
4438 if (dictnsItem == tmp->value)
4439 break;
4440 tmp = tmp->next;
4441 }
4442 if (tmp == NULL) {
4443 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4444 if (tmp == NULL) {
4445 xmlFree(nsItem);
4446 return (-1);
4447 }
4448 tmp->value = dictnsItem;
4449 tmp->next = NULL;
4450 if (wildc->nsSet == NULL)
4451 wildc->nsSet = tmp;
4452 else
4453 lastNs->next = tmp;
4454 lastNs = tmp;
4455 }
4456
4457 }
4458 xmlFree(nsItem);
4459 cur = end;
4460 } while (*cur != 0);
4461 }
4462 return (ret);
4463}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004464
4465static int
4466xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4467 xmlSchemaTypePtr item,
4468 xmlNodePtr node,
4469 int minOccurs,
4470 int maxOccurs) {
4471
4472 if (maxOccurs != UNBOUNDED) {
4473 /*
4474 * TODO: Maby we should better not create the particle,
4475 * if min/max is invalid, since it could confuse the build of the
4476 * content model.
4477 */
4478 /*
4479 * 3.9.6 Schema Component Constraint: Particle Correct
4480 *
4481 */
4482 if (maxOccurs < 1) {
4483 /*
4484 * 2.2 {max occurs} must be greater than or equal to 1.
4485 */
4486 xmlSchemaPCustomAttrErr(ctxt,
4487 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4488 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4489 "The value must be greater than or equal to 1");
4490 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4491 } else if (minOccurs > maxOccurs) {
4492 /*
4493 * 2.1 {min occurs} must not be greater than {max occurs}.
4494 */
4495 xmlSchemaPCustomAttrErr(ctxt,
4496 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4497 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4498 "The value must not be greater than the value of 'maxOccurs'");
4499 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4500 }
4501 }
4502 return (0);
4503}
4504
Daniel Veillardc0826a72004-08-10 14:17:33 +00004505/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004506 * xmlSchemaParseAny:
4507 * @ctxt: a schema validation context
4508 * @schema: the schema being built
4509 * @node: a subtree containing XML Schema informations
4510 *
4511 * parse a XML schema Any declaration
4512 * *WARNING* this interface is highly subject to change
4513 *
4514 * Returns the new type structure or NULL in case of error
4515 */
4516static xmlSchemaTypePtr
4517xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4518 xmlNodePtr node)
4519{
4520 xmlSchemaTypePtr type;
4521 xmlNodePtr child = NULL;
4522 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004523 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004524 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004525
4526 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4527 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004528 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4529 "(nonNegativeInteger | unbounded)");
4530 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4531 "nonNegativeInteger");
4532 if ((minOccurs == 0) && (maxOccurs == 0))
4533 return (NULL);
4534
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004535 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004536 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004538 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004540 type->type = XML_SCHEMA_TYPE_ANY;
4541
Daniel Veillardc0826a72004-08-10 14:17:33 +00004542 wildc = xmlSchemaAddWildcard(ctxt);
4543 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004544 * Check min/max sanity.
4545 */
4546 type->maxOccurs = maxOccurs;
4547 type->minOccurs = minOccurs;
4548 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4549 node, type->minOccurs, type->maxOccurs);
4550 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004551 * This is not nice, since it is won't be used as a attribute wildcard,
4552 * but better than adding a field to the structure.
4553 */
4554 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004555 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004556 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004558 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4559 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 }
4561 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004562 xmlSchemaPErr2(ctxt, node, child,
4563 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4564 "Sequence %s has unexpected content\n", type->name,
4565 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 }
4567
4568 return (type);
4569}
4570
4571/**
4572 * xmlSchemaParseNotation:
4573 * @ctxt: a schema validation context
4574 * @schema: the schema being built
4575 * @node: a subtree containing XML Schema informations
4576 *
4577 * parse a XML schema Notation declaration
4578 *
4579 * Returns the new structure or NULL in case of error
4580 */
4581static xmlSchemaNotationPtr
4582xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004584{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004585 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004586 xmlSchemaNotationPtr ret;
4587 xmlNodePtr child = NULL;
4588
4589 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4590 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004591 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004593 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4594 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004595 return (NULL);
4596 }
4597 ret = xmlSchemaAddNotation(ctxt, schema, name);
4598 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004599 return (NULL);
4600 }
4601 child = node->children;
4602 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004603 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4604 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004605 }
4606 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004607 xmlSchemaPErr2(ctxt, node, child,
4608 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4609 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004610 }
4611
4612 return (ret);
4613}
4614
4615/**
4616 * xmlSchemaParseAnyAttribute:
4617 * @ctxt: a schema validation context
4618 * @schema: the schema being built
4619 * @node: a subtree containing XML Schema informations
4620 *
4621 * parse a XML schema AnyAttrribute declaration
4622 * *WARNING* this interface is highly subject to change
4623 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004624 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004625 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004626static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004627xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4628 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004629{
Daniel Veillard3646d642004-06-02 19:19:14 +00004630 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004631 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004632 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004633
4634 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4635 return (NULL);
4636
Daniel Veillard3646d642004-06-02 19:19:14 +00004637 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004638 if (ret == NULL) {
4639 return (NULL);
4640 }
William M. Bracke7091952004-05-11 15:09:58 +00004641 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004642 /*
4643 * Check for illegal attributes.
4644 */
4645 attr = node->properties;
4646 while (attr != NULL) {
4647 if (attr->ns == NULL) {
4648 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4649 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4650 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4651 xmlSchemaPIllegalAttrErr(ctxt,
4652 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4653 NULL, NULL, attr);
4654 }
4655 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4656 xmlSchemaPIllegalAttrErr(ctxt,
4657 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4658 NULL, NULL, attr);
4659 }
4660 attr = attr->next;
4661 }
4662 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4663 /*
4664 * Parse the namespace list.
4665 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004666 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4667 xmlSchemaFreeWildcard(ret);
4668 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004669 }
4670 /*
4671 * And now for the children...
4672 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004673 child = node->children;
4674 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004675 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4676 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004677 }
4678 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004679 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004680 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4681 NULL, NULL, node, child,
4682 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004683 }
4684
4685 return (ret);
4686}
4687
4688
4689/**
4690 * xmlSchemaParseAttribute:
4691 * @ctxt: a schema validation context
4692 * @schema: the schema being built
4693 * @node: a subtree containing XML Schema informations
4694 *
4695 * parse a XML schema Attrribute declaration
4696 * *WARNING* this interface is highly subject to change
4697 *
William M. Bracke7091952004-05-11 15:09:58 +00004698 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004699 */
4700static xmlSchemaAttributePtr
4701xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004702 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004703{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004704 const xmlChar *name, *attrValue;
4705 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004706 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004707 xmlNodePtr child = NULL;
4708 xmlAttrPtr attr, nameAttr;
4709 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004710
4711 /*
4712 * Note that the w3c spec assumes the schema to be validated with schema
4713 * for schemas beforehand.
4714 *
4715 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004716 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004717
4718 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4719 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004720 attr = xmlSchemaGetPropNode(node, "ref");
4721 nameAttr = xmlSchemaGetPropNode(node, "name");
4722
4723 if ((attr == NULL) && (nameAttr == NULL)) {
4724 /*
4725 * 3.2.3 : 3.1
4726 * One of ref or name must be present, but not both
4727 */
4728 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4729 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4730 "One of the attributes 'ref' or 'name' must be present");
4731 return (NULL);
4732 }
4733 if ((topLevel) || (attr == NULL)) {
4734 if (nameAttr == NULL) {
4735 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4736 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4737 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004738 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004739 }
4740 } else
4741 isRef = 1;
4742
4743 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004744 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004745 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4746
4747 /*
4748 * Parse as attribute reference.
4749 */
4750 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4751 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4752 &refPrefix, &ref) != 0) {
4753 return (NULL);
4754 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004755 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004756 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004757 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004758 if (ret == NULL) {
4759 if (repName != NULL)
4760 xmlFree(repName);
4761 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004762 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004763 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4764 ret->node = node;
4765 ret->refNs = refNs;
4766 ret->refPrefix = refPrefix;
4767 ret->ref = ref;
4768 /*
4769 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4770 */
4771 if (nameAttr != NULL)
4772 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4773 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4774 "ref", "name");
4775 /*
4776 * Check for illegal attributes.
4777 */
4778 attr = node->properties;
4779 while (attr != NULL) {
4780 if (attr->ns == NULL) {
4781 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4782 xmlStrEqual(attr->name, BAD_CAST "form")) {
4783 /*
4784 * 3.2.3 : 3.2
4785 * If ref is present, then all of <simpleType>,
4786 * form and type must be absent.
4787 */
4788 xmlSchemaPIllegalAttrErr(ctxt,
4789 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4790 (xmlSchemaTypePtr) ret, attr);
4791 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4792 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4793 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4794 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4795 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4796 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4797 xmlSchemaPIllegalAttrErr(ctxt,
4798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4799 &repName, (xmlSchemaTypePtr) ret, attr);
4800 }
4801 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4802 xmlSchemaPIllegalAttrErr(ctxt,
4803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4804 &repName, (xmlSchemaTypePtr) ret, attr);
4805 }
4806 attr = attr->next;
4807 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004808 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004809 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004810
4811 /*
4812 * Parse as attribute declaration.
4813 */
4814 if (xmlSchemaPValAttrNode(ctxt,
4815 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4816 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4817 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004818 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004819 /*
4820 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4821 */
4822 /*
4823 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4824 */
4825 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4826 xmlSchemaPSimpleTypeErr(ctxt,
4827 XML_SCHEMAP_NO_XMLNS,
4828 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004829 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004830 "The value must not match 'xmlns'",
4831 NULL, NULL);
4832 if (repName != NULL)
4833 xmlFree(repName);
4834 return (NULL);
4835 }
4836 /*
4837 * Evaluate the target namespace
4838 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004839 if (topLevel) {
4840 ns = schema->targetNamespace;
4841 } else {
4842 attr = xmlSchemaGetPropNode(node, "form");
4843 if (attr != NULL) {
4844 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4845 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4846 ns = schema->targetNamespace;
4847 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4848 xmlSchemaPSimpleTypeErr(ctxt,
4849 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4850 &repName, NULL, (xmlNodePtr) attr,
4851 NULL, "(qualified | unqualified)",
4852 attrValue, NULL, NULL, NULL);
4853 }
4854 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4855 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004856 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004857 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004858 if (ret == NULL) {
4859 if (repName != NULL)
4860 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004861 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004862 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004863 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4864 ret->node = node;
4865 if (topLevel)
4866 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4867 /*
4868 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4869 */
4870 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4871 xmlSchemaPCustomErr(ctxt,
4872 XML_SCHEMAP_NO_XSI,
4873 &repName, (xmlSchemaTypePtr) ret, node,
4874 "The target namespace must not match '%s'",
4875 xmlSchemaInstanceNs);
4876 }
4877 /*
4878 * Check for illegal attributes.
4879 */
4880 attr = node->properties;
4881 while (attr != NULL) {
4882 if (attr->ns == NULL) {
4883 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4884 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4885 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4886 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4887 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4888 if ((topLevel) ||
4889 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4890 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4891 xmlSchemaPIllegalAttrErr(ctxt,
4892 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4893 &repName, (xmlSchemaTypePtr) ret, attr);
4894 }
4895 }
4896 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4897 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4898 &repName, (xmlSchemaTypePtr) ret, attr);
4899 }
4900 attr = attr->next;
4901 }
4902 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4903 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004904 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004905 /* TODO: Check ID. */
4906 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004907 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004908 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004909 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004910 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4911 if (ret->defValue != NULL)
4912 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4913 /*
4914 * Attribute "default".
4915 */
4916 attr = xmlSchemaGetPropNode(node, "default");
4917 if (attr != NULL) {
4918 /*
4919 * 3.2.3 : 1
4920 * default and fixed must not both be present.
4921 */
4922 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4923 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4924 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4925 } else
4926 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4927 }
4928 if (topLevel == 0) {
4929 /*
4930 * Attribute "use".
4931 */
4932 attr = xmlSchemaGetPropNode(node, "use");
4933 if (attr != NULL) {
4934 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4935 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4936 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4937 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4938 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4939 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4940 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4941 else
4942 xmlSchemaPSimpleTypeErr(ctxt,
4943 XML_SCHEMAP_INVALID_ATTR_USE,
4944 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004945 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004946 attrValue, NULL, NULL, NULL);
4947 } else
4948 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4949 /*
4950 * 3.2.3 : 2
4951 * If default and use are both present, use must have
4952 * the actual value optional.
4953 */
4954 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4955 (ret->defValue != NULL) &&
4956 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4957 xmlSchemaPSimpleTypeErr(ctxt,
4958 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4959 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004960 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004961 "The value must be 'optional' if the attribute "
4962 "'default' is present as well", NULL, NULL);
4963 }
4964 }
4965 /*
4966 * And now for the children...
4967 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004968 child = node->children;
4969 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004970 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4971 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004972 }
4973 if (isRef) {
4974 if (child != NULL) {
4975 if (IS_SCHEMA(child, "simpleType"))
4976 /*
4977 * 3.2.3 : 3.2
4978 * If ref is present, then all of <simpleType>,
4979 * form and type must be absent.
4980 */
4981 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4982 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4983 "(annotation?)");
4984 else
4985 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4986 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4987 "(annotation?)");
4988 }
4989 } else {
4990 if (IS_SCHEMA(child, "simpleType")) {
4991 if (ret->typeName != NULL) {
4992 /*
4993 * 3.2.3 : 4
4994 * type and <simpleType> must not both be present.
4995 */
4996 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4997 &repName, (xmlSchemaTypePtr) ret, node, child,
4998 "The attribute 'type' and the <simpleType> child "
4999 "are mutually exclusive", NULL);
5000 } else
5001 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5002 child = child->next;
5003 }
5004 if (child != NULL)
5005 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5006 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5007 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005008 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005009 /*
5010 * Cleanup.
5011 */
5012 if (repName != NULL)
5013 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005014 return (ret);
5015}
5016
5017/**
5018 * xmlSchemaParseAttributeGroup:
5019 * @ctxt: a schema validation context
5020 * @schema: the schema being built
5021 * @node: a subtree containing XML Schema informations
5022 *
5023 * parse a XML schema Attribute Group declaration
5024 * *WARNING* this interface is highly subject to change
5025 *
5026 * Returns the attribute group or NULL in case of error.
5027 */
5028static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005029xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005030 xmlSchemaPtr schema, xmlNodePtr node,
5031 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005032{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005033 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005034 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005035 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005036 const xmlChar *oldcontainer;
5037 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005038
5039 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5040 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005041
5042 nameAttr = xmlSchemaGetPropNode(node, "name");
5043 attr = xmlSchemaGetPropNode(node, "ref");
5044 if ((topLevel) || (attr == NULL)) {
5045 /*
5046 * Parse as an attribute group definition.
5047 * Note that those are allowed at top level only.
5048 */
5049 if (nameAttr == NULL) {
5050 xmlSchemaPMissingAttrErr(ctxt,
5051 XML_SCHEMAP_S4S_ATTR_MISSING,
5052 NULL, NULL, node, "name", NULL);
5053 return (NULL);
5054 }
5055 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5056 /*
5057 * The name is crucial, exit if invalid.
5058 */
5059 if (xmlSchemaPValAttrNode(ctxt,
5060 NULL, NULL, nameAttr,
5061 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5062 return (NULL);
5063 }
5064 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5065 if (ret == NULL)
5066 return (NULL);
5067 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5068 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5069 ret->node = node;
5070 } else {
5071 char buf[50];
5072 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5073
5074 /*
5075 * Parse as an attribute group definition reference.
5076 */
5077 if (attr == NULL) {
5078 xmlSchemaPMissingAttrErr(ctxt,
5079 XML_SCHEMAP_S4S_ATTR_MISSING,
5080 NULL, NULL, node, "ref", NULL);
5081 }
5082 xmlSchemaPValAttrNodeQName(ctxt, schema,
5083 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5084
5085 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5086 name = (const xmlChar *) buf;
5087 if (name == NULL) {
5088 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5089 "attribute group definition reference", node);
5090 return (NULL);
5091 }
5092 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5093 if (ret == NULL)
5094 return (NULL);
5095 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5096 ret->ref = ref;
5097 ret->refNs = refNs;
5098 /* TODO: Is @refPrefix currently used? */
5099 ret->refPrefix = refPrefix;
5100 ret->node = node;
5101 }
5102 /*
5103 * Check for illegal attributes.
5104 */
5105 attr = node->properties;
5106 while (attr != NULL) {
5107 if (attr->ns == NULL) {
5108 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5109 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5110 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5111 {
5112 xmlSchemaPIllegalAttrErr(ctxt,
5113 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5114 NULL, NULL, attr);
5115 }
5116 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5117 xmlSchemaPIllegalAttrErr(ctxt,
5118 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5119 NULL, NULL, attr);
5120 }
5121 attr = attr->next;
5122 }
5123 /* TODO: Validate "id" ? */
5124 /*
5125 * And now for the children...
5126 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005127 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005128 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005129 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005130 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005131 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5132 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005133 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005134 if (topLevel) {
5135 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5136 if (IS_SCHEMA(child, "anyAttribute")) {
5137 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5138 child = child->next;
5139 }
5140 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005141 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005142 xmlSchemaPContentErr(ctxt,
5143 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5144 NULL, NULL, node, child, NULL,
5145 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005146 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005147 ctxt->container = oldcontainer;
5148 return (ret);
5149}
5150
5151/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005152 * xmlSchemaPValAttrFormDefault:
5153 * @value: the value
5154 * @flags: the flags to be modified
5155 * @flagQualified: the specific flag for "qualified"
5156 *
5157 * Returns 0 if the value is valid, 1 otherwise.
5158 */
5159static int
5160xmlSchemaPValAttrFormDefault(const xmlChar *value,
5161 int *flags,
5162 int flagQualified)
5163{
5164 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5165 if ((*flags & flagQualified) == 0)
5166 *flags |= flagQualified;
5167 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5168 return (1);
5169
5170 return (0);
5171}
5172
5173/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005174 * xmlSchemaPValAttrBlockFinal:
5175 * @value: the value
5176 * @flags: the flags to be modified
5177 * @flagAll: the specific flag for "#all"
5178 * @flagExtension: the specific flag for "extension"
5179 * @flagRestriction: the specific flag for "restriction"
5180 * @flagSubstitution: the specific flag for "substitution"
5181 * @flagList: the specific flag for "list"
5182 * @flagUnion: the specific flag for "union"
5183 *
5184 * Validates the value of the attribute "final" and "block". The value
5185 * is converted into the specified flag values and returned in @flags.
5186 *
5187 * Returns 0 if the value is valid, 1 otherwise.
5188 */
5189
5190static int
5191xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5192 int *flags,
5193 int flagAll,
5194 int flagExtension,
5195 int flagRestriction,
5196 int flagSubstitution,
5197 int flagList,
5198 int flagUnion)
5199{
5200 int ret = 0;
5201
5202 /*
5203 * TODO: This does not check for dublicate entries.
5204 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005205 if (value == NULL)
5206 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005207 if (xmlStrEqual(value, BAD_CAST "#all")) {
5208 if (flagAll != -1)
5209 *flags |= flagAll;
5210 else {
5211 if (flagExtension != -1)
5212 *flags |= flagExtension;
5213 if (flagRestriction != -1)
5214 *flags |= flagRestriction;
5215 if (flagSubstitution != -1)
5216 *flags |= flagSubstitution;
5217 if (flagList != -1)
5218 *flags |= flagList;
5219 if (flagUnion != -1)
5220 *flags |= flagUnion;
5221 }
5222 } else {
5223 const xmlChar *end, *cur = value;
5224 xmlChar *item;
5225
5226 do {
5227 while (IS_BLANK_CH(*cur))
5228 cur++;
5229 end = cur;
5230 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5231 end++;
5232 if (end == cur)
5233 break;
5234 item = xmlStrndup(cur, end - cur);
5235 if (xmlStrEqual(item, BAD_CAST "extension")) {
5236 if (flagExtension != -1) {
5237 if ((*flags & flagExtension) == 0)
5238 *flags |= flagExtension;
5239 } else
5240 ret = 1;
5241 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5242 if (flagRestriction != -1) {
5243 if ((*flags & flagRestriction) == 0)
5244 *flags |= flagRestriction;
5245 } else
5246 ret = 1;
5247 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5248 if (flagSubstitution != -1) {
5249 if ((*flags & flagSubstitution) == 0)
5250 *flags |= flagSubstitution;
5251 } else
5252 ret = 1;
5253 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5254 if (flagList != -1) {
5255 if ((*flags & flagList) == 0)
5256 *flags |= flagList;
5257 } else
5258 ret = 1;
5259 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5260 if (flagUnion != -1) {
5261 if ((*flags & flagUnion) == 0)
5262 *flags |= flagUnion;
5263 } else
5264 ret = 1;
5265 } else
5266 ret = 1;
5267 if (item != NULL)
5268 xmlFree(item);
5269 cur = end;
5270 } while ((ret == 0) && (*cur != 0));
5271 }
5272
5273 return (ret);
5274}
5275
5276/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005277 * xmlSchemaParseElement:
5278 * @ctxt: a schema validation context
5279 * @schema: the schema being built
5280 * @node: a subtree containing XML Schema informations
5281 *
5282 * parse a XML schema Element declaration
5283 * *WARNING* this interface is highly subject to change
5284 *
William M. Bracke7091952004-05-11 15:09:58 +00005285 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005286 */
5287static xmlSchemaElementPtr
5288xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005289 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005290{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005291 const xmlChar *name = NULL;
5292 const xmlChar *attrValue;
5293 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005294 xmlSchemaElementPtr ret;
5295 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005296 const xmlChar *oldcontainer;
5297 xmlAttrPtr attr, nameAttr;
5298 int minOccurs, maxOccurs;
5299 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005300
5301 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5302 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005303
Daniel Veillard4255d502002-04-16 15:50:10 +00005304 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5305 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005306
Daniel Veillardc0826a72004-08-10 14:17:33 +00005307 oldcontainer = ctxt->container;
5308
5309 nameAttr = xmlSchemaGetPropNode(node, "name");
5310 attr = xmlSchemaGetPropNode(node, "ref");
5311 if ((topLevel) || (attr == NULL)) {
5312 if (nameAttr == NULL) {
5313 xmlSchemaPMissingAttrErr(ctxt,
5314 XML_SCHEMAP_S4S_ATTR_MISSING,
5315 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5316 "name", NULL);
5317 return (NULL);
5318 }
5319 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5320 } else {
5321 isRef = 1;
5322
5323 }
5324 /*
5325 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5326 * to no component at all
5327 * TODO: It might be better to validate the element, even if it won't be
5328 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005329 */
5330 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5331 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005332 if ((minOccurs == 0) && (maxOccurs == 0))
5333 return (NULL);
5334 /*
5335 * If we get a "ref" attribute on a local <element> we will assume it's
5336 * a reference - even if there's a "name" attribute; this seems to be more
5337 * robust.
5338 */
5339 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005340 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005341 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5342
5343 /*
5344 * Parse as a particle.
5345 */
5346 xmlSchemaPValAttrNodeQName(ctxt, schema,
5347 (xmlChar **) &xmlSchemaElemDesAttrRef,
5348 NULL, attr, &refNs, &refPrefix, &ref);
5349
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005350 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005351 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 if (ret == NULL) {
5353 if (repName != NULL)
5354 xmlFree(repName);
5355 return (NULL);
5356 }
5357 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5358 ret->node = node;
5359 ret->ref = ref;
5360 ret->refNs = refNs;
5361 ret->refPrefix = refPrefix;
5362 ret->flags |= XML_SCHEMAS_ELEM_REF;
5363 /*
5364 * Check for illegal attributes.
5365 */
5366 /*
5367 * 3.3.3 : 2.1
5368 * One of ref or name must be present, but not both
5369 */
5370 if (nameAttr != NULL) {
5371 xmlSchemaPMutualExclAttrErr(ctxt,
5372 XML_SCHEMAP_SRC_ELEMENT_2_1,
5373 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5374 "ref", "name");
5375 }
5376 /* 3.3.3 : 2.2 */
5377 attr = node->properties;
5378 while (attr != NULL) {
5379 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005380 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5381 xmlStrEqual(attr->name, BAD_CAST "name") ||
5382 xmlStrEqual(attr->name, BAD_CAST "id") ||
5383 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5384 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5385 {
5386 attr = attr->next;
5387 continue;
5388 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005389 xmlSchemaPCustomAttrErr(ctxt,
5390 XML_SCHEMAP_SRC_ELEMENT_2_2,
5391 &repName, (xmlSchemaTypePtr) ret, attr,
5392 "Only the attributes 'minOccurs', 'maxOccurs' and "
5393 "'id' are allowed in addition to 'ref'");
5394 break;
5395 }
5396 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5397 xmlSchemaPIllegalAttrErr(ctxt,
5398 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5399 &repName, (xmlSchemaTypePtr) ret, attr);
5400 }
5401 attr = attr->next;
5402 }
5403 } else {
5404 const xmlChar *ns = NULL, *fixed;
5405
5406 /*
5407 * Parse as an element declaration.
5408 */
5409 if (xmlSchemaPValAttrNode(ctxt,
5410 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5411 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5412 return (NULL);
5413 /*
5414 * Evaluate the target namespace.
5415 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005416 if (topLevel) {
5417 ns = schema->targetNamespace;
5418 } else {
5419 attr = xmlSchemaGetPropNode(node, "form");
5420 if (attr != NULL) {
5421 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5422 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005423 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005424 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5425 xmlSchemaPSimpleTypeErr(ctxt,
5426 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5427 &repName, NULL, (xmlNodePtr) attr,
5428 NULL, "(qualified | unqualified)",
5429 attrValue, NULL, NULL, NULL);
5430 }
5431 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5432 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005433 }
5434 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005435 if (ret == NULL) {
5436 if (repName != NULL)
5437 xmlFree(repName);
5438 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005439 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005440 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5441 ret->node = node;
5442 /*
5443 * Check for illegal attributes.
5444 */
William M. Bracke7091952004-05-11 15:09:58 +00005445 attr = node->properties;
5446 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005447 if (attr->ns == NULL) {
5448 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5449 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5450 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5451 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5452 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5453 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005454 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5455 {
5456 if (topLevel == 0) {
5457 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005458 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005459 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5460 {
5461 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5462 /*
5463 * 3.3.6 : 3 If there is a non-·absent· {substitution
5464 * group affiliation}, then {scope} must be global.
5465 * TODO: This one is redundant, since the S4S does
5466 * prohibit this attribute on local declarations already;
5467 * so why an explicit error code? Weird spec.
5468 * TODO: Move this to the proper constraint layer.
5469 * TODO: Or better wait for spec 1.1 to come.
5470 */
5471 xmlSchemaPIllegalAttrErr(ctxt,
5472 XML_SCHEMAP_E_PROPS_CORRECT_3,
5473 &repName, (xmlSchemaTypePtr) ret, attr);
5474 } else {
5475 xmlSchemaPIllegalAttrErr(ctxt,
5476 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5477 &repName, (xmlSchemaTypePtr) ret, attr);
5478 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005479 }
5480 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5481 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5482 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5483
5484 xmlSchemaPIllegalAttrErr(ctxt,
5485 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5486 &repName, (xmlSchemaTypePtr) ret, attr);
5487 }
5488 }
5489 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5490
5491 xmlSchemaPIllegalAttrErr(ctxt,
5492 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5493 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005494 }
5495 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005496 }
William M. Bracke7091952004-05-11 15:09:58 +00005497 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005498 * Extract/validate attributes.
5499 */
5500 if (topLevel) {
5501 /*
5502 * Process top attributes of global element declarations here.
5503 */
5504 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5505 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5506 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5507 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5508 &(ret->substGroupNs), NULL, &(ret->substGroup));
5509 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5510 node, "abstract", 0))
5511 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5512 /*
5513 * Attribute "final".
5514 */
5515 attr = xmlSchemaGetPropNode(node, "final");
5516 if (attr == NULL) {
5517 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5518 } else {
5519 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5520 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5521 -1,
5522 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5523 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5524 xmlSchemaPSimpleTypeErr(ctxt,
5525 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5526 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005527 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005528 attrValue, NULL, NULL, NULL);
5529 }
5530 }
5531 }
5532 /*
5533 * Attribute "block".
5534 */
5535 attr = xmlSchemaGetPropNode(node, "block");
5536 if (attr == NULL) {
5537 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5538 } else {
5539 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5540 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5541 -1,
5542 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5543 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5544 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5545 xmlSchemaPSimpleTypeErr(ctxt,
5546 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5547 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005548 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005549 "restriction | substitution))", attrValue,
5550 NULL, NULL, NULL);
5551 }
5552 }
5553 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5554 node, "nillable", 0))
5555 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005556
Daniel Veillardc0826a72004-08-10 14:17:33 +00005557 xmlSchemaPValAttrQName(ctxt, schema,
5558 &repName, (xmlSchemaTypePtr) ret, node,
5559 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005560
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5562 attr = xmlSchemaGetPropNode(node, "fixed");
5563 if (attr != NULL) {
5564 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5565 if (ret->value != NULL) {
5566 /*
5567 * 3.3.3 : 1
5568 * default and fixed must not both be present.
5569 */
5570 xmlSchemaPMutualExclAttrErr(ctxt,
5571 XML_SCHEMAP_SRC_ELEMENT_1,
5572 &repName, (xmlSchemaTypePtr) ret, attr,
5573 "default", "fixed");
5574 } else {
5575 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5576 ret->value = fixed;
5577 }
5578 }
5579 }
5580 /*
5581 * Extract/validate common attributes.
5582 */
5583 /* TODO: Check ID: */
5584 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5585 ret->minOccurs = minOccurs;
5586 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005587 if (topLevel != 1)
5588 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5589 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 /*
5591 * And now for the children...
5592 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005593 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005594 child = node->children;
5595 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005596 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5597 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005598 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005599 if (isRef) {
5600 if (child != NULL) {
5601 xmlSchemaPContentErr(ctxt,
5602 XML_SCHEMAP_SRC_ELEMENT_2_2,
5603 &repName, (xmlSchemaTypePtr) ret, node, child,
5604 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005605 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005606 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005607 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608 /*
5609 * 3.3.3 : 3
5610 * "type" and either <simpleType> or <complexType> are mutually
5611 * exclusive
5612 */
William M. Bracke7091952004-05-11 15:09:58 +00005613 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 xmlSchemaPContentErr(ctxt,
5615 XML_SCHEMAP_SRC_ELEMENT_3,
5616 &repName, (xmlSchemaTypePtr) ret, node, child,
5617 "The attribute 'type' and the <complexType> child are "
5618 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005619 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005620 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005621 child = child->next;
5622 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005623 /*
5624 * 3.3.3 : 3
5625 * "type" and either <simpleType> or <complexType> are
5626 * mutually exclusive
5627 */
William M. Bracke7091952004-05-11 15:09:58 +00005628 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005629 xmlSchemaPContentErr(ctxt,
5630 XML_SCHEMAP_SRC_ELEMENT_3,
5631 &repName, (xmlSchemaTypePtr) ret, node, child,
5632 "The attribute 'type' and the <simpleType> child are "
5633 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005634 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005635 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005636 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005637 }
William M. Bracke7091952004-05-11 15:09:58 +00005638 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005639 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcik48307f42004-11-12 15:16:25 +00005640 TODO child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00005641 }
5642 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005643 xmlSchemaPContentErr(ctxt,
5644 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5645 &repName, (xmlSchemaTypePtr) ret, node, child,
5646 NULL, "(annotation?, ((simpleType | complexType)?, "
5647 "(unique | key | keyref)*))");
5648 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005649
Daniel Veillardc0826a72004-08-10 14:17:33 +00005650 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005651 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005652 /*
5653 * Cleanup.
5654 */
5655 if (repName != NULL)
5656 xmlFree(repName);
5657 /*
5658 * NOTE: Element Declaration Representation OK 4. will be checked at a
5659 * different layer.
5660 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 return (ret);
5662}
5663
5664/**
5665 * xmlSchemaParseUnion:
5666 * @ctxt: a schema validation context
5667 * @schema: the schema being built
5668 * @node: a subtree containing XML Schema informations
5669 *
5670 * parse a XML schema Union definition
5671 * *WARNING* this interface is highly subject to change
5672 *
William M. Bracke7091952004-05-11 15:09:58 +00005673 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005674 * 1 in case of success.
5675 */
5676static xmlSchemaTypePtr
5677xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005678 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005679{
5680 xmlSchemaTypePtr type, subtype, last = NULL;
5681 xmlNodePtr child = NULL;
5682 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005683 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005684
5685 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5686 return (NULL);
5687
William M. Brack2f2a6632004-08-20 23:09:47 +00005688 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5689 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 if (type == NULL)
5691 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005692 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005693 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005694 /*
5695 * Check for illegal attributes.
5696 */
5697 attr = node->properties;
5698 while (attr != NULL) {
5699 if (attr->ns == NULL) {
5700 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5701 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5702 xmlSchemaPIllegalAttrErr(ctxt,
5703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5704 NULL, type, attr);
5705 }
5706 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5707 xmlSchemaPIllegalAttrErr(ctxt,
5708 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5709 NULL, type, attr);
5710 }
5711 attr = attr->next;
5712 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005713 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005714 /*
5715 * Attribute "memberTypes". This is a list of QNames.
5716 * TODO: Validate the QNames.
5717 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005718 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005719 /*
5720 * And now for the children...
5721 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005722 child = node->children;
5723 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005724 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5725 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005726 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005727 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005728 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005729 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005730 if (subtype != NULL) {
5731 if (last == NULL) {
5732 type->subtypes = subtype;
5733 last = subtype;
5734 } else {
5735 last->next = subtype;
5736 last = subtype;
5737 }
5738 last->next = NULL;
5739 }
5740 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005741 }
5742 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005743 /* TODO: Think about the error code. */
5744 xmlSchemaPContentErr(ctxt,
5745 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5746 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005747 }
5748 return (type);
5749}
5750
5751/**
5752 * xmlSchemaParseList:
5753 * @ctxt: a schema validation context
5754 * @schema: the schema being built
5755 * @node: a subtree containing XML Schema informations
5756 *
5757 * parse a XML schema List definition
5758 * *WARNING* this interface is highly subject to change
5759 *
William M. Bracke7091952004-05-11 15:09:58 +00005760 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005761 * 1 in case of success.
5762 */
5763static xmlSchemaTypePtr
5764xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005765 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005766{
5767 xmlSchemaTypePtr type, subtype;
5768 xmlNodePtr child = NULL;
5769 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005771
5772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5773 return (NULL);
5774
William M. Brack2f2a6632004-08-20 23:09:47 +00005775 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5776 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005777 if (type == NULL)
5778 return (NULL);
5779 type->node = node;
5780 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005781 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005782 /*
5783 * Check for illegal attributes.
5784 */
5785 attr = node->properties;
5786 while (attr != NULL) {
5787 if (attr->ns == NULL) {
5788 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5789 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5790 xmlSchemaPIllegalAttrErr(ctxt,
5791 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5792 NULL, type, attr);
5793 }
5794 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5795 xmlSchemaPIllegalAttrErr(ctxt,
5796 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5797 NULL, type, attr);
5798 }
5799 attr = attr->next;
5800 }
5801 /*
5802 * Attribute "itemType".
5803 */
5804 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5805 node, "itemType", &(type->baseNs), NULL, &(type->base));
5806 /*
5807 * And now for the children...
5808 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 child = node->children;
5810 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005811 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5812 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005813 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005814 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005815 if (IS_SCHEMA(child, "simpleType")) {
5816 if (type->base != NULL) {
5817 xmlSchemaPCustomErr(ctxt,
5818 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5819 NULL, type, node,
5820 "The attribute 'itemType' and the <simpleType> child "
5821 "are mutually exclusive", NULL);
5822 } else {
5823 subtype = (xmlSchemaTypePtr)
5824 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5825 type->subtypes = subtype;
5826 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005827 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005828 }
5829 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005830 /* TODO: Think about the error code. */
5831 xmlSchemaPContentErr(ctxt,
5832 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5833 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005834 }
5835 return (type);
5836}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005837
Daniel Veillard4255d502002-04-16 15:50:10 +00005838/**
5839 * xmlSchemaParseSimpleType:
5840 * @ctxt: a schema validation context
5841 * @schema: the schema being built
5842 * @node: a subtree containing XML Schema informations
5843 *
5844 * parse a XML schema Simple Type definition
5845 * *WARNING* this interface is highly subject to change
5846 *
William M. Bracke7091952004-05-11 15:09:58 +00005847 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005848 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005849 */
5850static xmlSchemaTypePtr
5851xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005852 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005853{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005854 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005855 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005856 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005857 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005859
5860 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5861 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005862
Daniel Veillardc0826a72004-08-10 14:17:33 +00005863 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005864 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005865 if (attr == NULL) {
5866 xmlSchemaPMissingAttrErr(ctxt,
5867 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005868 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005869 "name", NULL);
5870 return (NULL);
5871 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005872 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005873 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005874 return (NULL);
5875 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005876 }
5877
5878 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005879 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005880
Daniel Veillard01fa6152004-06-29 17:04:39 +00005881 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005882 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005883 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005884 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005885 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005886 if (type == NULL)
5887 return (NULL);
5888 type->node = node;
5889 type->type = XML_SCHEMA_TYPE_SIMPLE;
5890 /*
5891 * Check for illegal attributes.
5892 */
5893 attr = node->properties;
5894 while (attr != NULL) {
5895 if (attr->ns == NULL) {
5896 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5897 xmlSchemaPIllegalAttrErr(ctxt,
5898 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005899 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005900 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005901 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5902 xmlSchemaPIllegalAttrErr(ctxt,
5903 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005904 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005905 }
5906 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005907 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005908 } else {
5909 /*
5910 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005911 *
5912 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005914 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005915 if (type == NULL)
5916 return (NULL);
5917 type->node = node;
5918 type->type = XML_SCHEMA_TYPE_SIMPLE;
5919 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5920 /*
5921 * Check for illegal attributes.
5922 */
5923 attr = node->properties;
5924 while (attr != NULL) {
5925 if (attr->ns == NULL) {
5926 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5927 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005928 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005929 xmlSchemaPIllegalAttrErr(ctxt,
5930 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005931 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005932 }
5933 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5934 xmlSchemaPIllegalAttrErr(ctxt,
5935 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005936 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005937 }
5938 attr = attr->next;
5939 }
5940 /*
5941 * Attribute "final".
5942 */
5943 attr = xmlSchemaGetPropNode(node, "final");
5944 if (attr == NULL) {
5945 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5946 } else {
5947 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5948 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5949 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5950 XML_SCHEMAS_TYPE_FINAL_LIST,
5951 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5952
5953 xmlSchemaPSimpleTypeErr(ctxt,
5954 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005955 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005956 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005957 attrValue, NULL, NULL, NULL);
5958 }
5959 }
5960 }
5961 /* TODO: Check id. */
5962 type->id = xmlSchemaGetProp(ctxt, node, "id");
5963 /*
5964 * And now for the children...
5965 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005966 oldCtxtType = ctxt->ctxtType;
5967 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005968 ctxt->ctxtType = type;
5969 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005970 child = node->children;
5971 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005972 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5973 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005974 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005975 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005976 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005977 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005978 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005979 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005981 subtype = (xmlSchemaTypePtr)
5982 xmlSchemaParseList(ctxt, schema, child);
5983 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005984 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005985 subtype = (xmlSchemaTypePtr)
5986 xmlSchemaParseUnion(ctxt, schema, child);
5987 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005988 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005989 type->subtypes = subtype;
5990 if ((child != NULL) || (subtype == NULL)) {
5991 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005992 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005993 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005994 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005995 ctxt->parentItem = oldParentItem;
5996 ctxt->ctxtType = oldCtxtType;
5997 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005998
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 return (type);
6000}
6001
6002
6003/**
6004 * xmlSchemaParseGroup:
6005 * @ctxt: a schema validation context
6006 * @schema: the schema being built
6007 * @node: a subtree containing XML Schema informations
6008 *
6009 * parse a XML schema Group definition
6010 * *WARNING* this interface is highly subject to change
6011 *
William M. Bracke7091952004-05-11 15:09:58 +00006012 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006013 * 1 in case of success.
6014 */
6015static xmlSchemaTypePtr
6016xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006017 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006018{
6019 xmlSchemaTypePtr type, subtype;
6020 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006021 const xmlChar *name;
6022 const xmlChar *ref = NULL, *refNs = NULL;
6023 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006024 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006025
6026 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6027 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006028 /*
6029 * TODO: Validate the element even if no item is created
6030 * (i.e. min/maxOccurs == 0).
6031 */
6032 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6033 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6034 if ((minOccurs == 0) && (maxOccurs == 0)) {
6035 return (NULL);
6036 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006037 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006038 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006039 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6040 if (ref == NULL) {
6041 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006042 XML_SCHEMAP_GROUP_NONAME_NOREF,
6043 "Group definition or particle: One of the attributes \"name\" "
6044 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006045 return (NULL);
6046 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006047 if (refNs == NULL)
6048 refNs = schema->targetNamespace;
6049 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
6050 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006052 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006053 if (type == NULL)
6054 return (NULL);
6055 type->node = node;
6056 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00006057 if (topLevel)
6058 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006059 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006060 type->ref = ref;
6061 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006062 type->minOccurs = minOccurs;
6063 type->maxOccurs = maxOccurs;
6064 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006065 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006066
6067 child = node->children;
6068 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006069 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6070 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006071 }
6072 subtype = NULL;
6073 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006074 subtype = (xmlSchemaTypePtr)
6075 xmlSchemaParseAll(ctxt, schema, child);
6076 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006077 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006078 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006080 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006081 subtype = (xmlSchemaTypePtr)
6082 xmlSchemaParseSequence(ctxt, schema, child);
6083 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006084 }
6085 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006086 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006089 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006090 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 }
6092
6093 return (type);
6094}
6095
6096/**
6097 * xmlSchemaParseAll:
6098 * @ctxt: a schema validation context
6099 * @schema: the schema being built
6100 * @node: a subtree containing XML Schema informations
6101 *
6102 * parse a XML schema All definition
6103 * *WARNING* this interface is highly subject to change
6104 *
William M. Bracke7091952004-05-11 15:09:58 +00006105 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006106 * 1 in case of success.
6107 */
6108static xmlSchemaTypePtr
6109xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006110 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006111{
6112 xmlSchemaTypePtr type, subtype, last = NULL;
6113 xmlNodePtr child = NULL;
6114 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006115 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006116
6117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6118 return (NULL);
6119
6120
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006121 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006122 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006123 if (type == NULL)
6124 return (NULL);
6125 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006126 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006127 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006128
6129 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6130 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006131
6132 oldcontainer = ctxt->container;
6133 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006134 child = node->children;
6135 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006136 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6137 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006138 }
6139 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006140 subtype = (xmlSchemaTypePtr)
6141 xmlSchemaParseElement(ctxt, schema, child, 0);
6142 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006143 if (subtype->minOccurs > 1)
6144 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006145 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006146 NULL, NULL);
6147 if (subtype->maxOccurs > 1)
6148 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006149 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006150 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006151 if (last == NULL) {
6152 type->subtypes = subtype;
6153 last = subtype;
6154 } else {
6155 last->next = subtype;
6156 last = subtype;
6157 }
6158 last->next = NULL;
6159 }
6160 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006161 }
6162 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006163 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006164 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006165 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006166 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006167 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006168 return (type);
6169}
6170
6171/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006172 * xmlSchemaCleanupDoc:
6173 * @ctxt: a schema validation context
6174 * @node: the root of the document.
6175 *
6176 * removes unwanted nodes in a schemas document tree
6177 */
6178static void
6179xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6180{
6181 xmlNodePtr delete, cur;
6182
6183 if ((ctxt == NULL) || (root == NULL)) return;
6184
6185 /*
6186 * Remove all the blank text nodes
6187 */
6188 delete = NULL;
6189 cur = root;
6190 while (cur != NULL) {
6191 if (delete != NULL) {
6192 xmlUnlinkNode(delete);
6193 xmlFreeNode(delete);
6194 delete = NULL;
6195 }
6196 if (cur->type == XML_TEXT_NODE) {
6197 if (IS_BLANK_NODE(cur)) {
6198 if (xmlNodeGetSpacePreserve(cur) != 1) {
6199 delete = cur;
6200 }
6201 }
6202 } else if ((cur->type != XML_ELEMENT_NODE) &&
6203 (cur->type != XML_CDATA_SECTION_NODE)) {
6204 delete = cur;
6205 goto skip_children;
6206 }
6207
6208 /*
6209 * Skip to next node
6210 */
6211 if (cur->children != NULL) {
6212 if ((cur->children->type != XML_ENTITY_DECL) &&
6213 (cur->children->type != XML_ENTITY_REF_NODE) &&
6214 (cur->children->type != XML_ENTITY_NODE)) {
6215 cur = cur->children;
6216 continue;
6217 }
6218 }
6219 skip_children:
6220 if (cur->next != NULL) {
6221 cur = cur->next;
6222 continue;
6223 }
6224
6225 do {
6226 cur = cur->parent;
6227 if (cur == NULL)
6228 break;
6229 if (cur == root) {
6230 cur = NULL;
6231 break;
6232 }
6233 if (cur->next != NULL) {
6234 cur = cur->next;
6235 break;
6236 }
6237 } while (cur != NULL);
6238 }
6239 if (delete != NULL) {
6240 xmlUnlinkNode(delete);
6241 xmlFreeNode(delete);
6242 delete = NULL;
6243 }
6244}
6245
William M. Brack2f2a6632004-08-20 23:09:47 +00006246
6247/**
6248 * xmlSchemaImportSchema
6249 *
6250 * @ctxt: a schema validation context
6251 * @schemaLocation: an URI defining where to find the imported schema
6252 *
6253 * import a XML schema
6254 * *WARNING* this interface is highly subject to change
6255 *
6256 * Returns -1 in case of error and 1 in case of success.
6257 */
6258#if 0
6259static xmlSchemaImportPtr
6260xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6261 const xmlChar *schemaLocation)
6262{
6263 xmlSchemaImportPtr import;
6264 xmlSchemaParserCtxtPtr newctxt;
6265
6266 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6267 if (newctxt == NULL) {
6268 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6269 NULL);
6270 return (NULL);
6271 }
6272 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6273 /* Keep the same dictionnary for parsing, really */
6274 xmlDictReference(ctxt->dict);
6275 newctxt->dict = ctxt->dict;
6276 newctxt->includes = 0;
6277 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6278
6279 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6280 ctxt->userData);
6281
6282 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6283 if (import == NULL) {
6284 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6285 NULL);
6286 xmlSchemaFreeParserCtxt(newctxt);
6287 return (NULL);
6288 }
6289
6290 memset(import, 0, sizeof(xmlSchemaImport));
6291 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6292 import->schema = xmlSchemaParse(newctxt);
6293
6294 if (import->schema == NULL) {
6295 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006296 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006297 "Failed to import schema from location \"%s\".\n",
6298 schemaLocation, NULL);
6299
6300 xmlSchemaFreeParserCtxt(newctxt);
6301 /* The schemaLocation is held by the dictionary.
6302 if (import->schemaLocation != NULL)
6303 xmlFree((xmlChar *)import->schemaLocation);
6304 */
6305 xmlFree(import);
6306 return NULL;
6307 }
6308
6309 xmlSchemaFreeParserCtxt(newctxt);
6310 return import;
6311}
6312#endif
6313
6314static void
6315xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6316{
6317 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6318 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6319
6320 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6321 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6322
6323 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6324 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6325 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6326 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6327 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6328 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6329 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6330 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6331
6332 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6333 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6334 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6335 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6336 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6337 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6338}
6339
6340static void
6341xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6342 xmlSchemaPtr schema,
6343 xmlNodePtr node)
6344{
6345 xmlAttrPtr attr;
6346 const xmlChar *val;
6347
6348 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6349 if (attr != NULL) {
6350 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6351 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6352 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6353 xmlSchemaPSimpleTypeErr(ctxt,
6354 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6355 NULL, NULL, (xmlNodePtr) attr, NULL,
6356 "(qualified | unqualified)", val, NULL, NULL, NULL);
6357 }
6358 }
6359
6360 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6361 if (attr != NULL) {
6362 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6363 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6364 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6365 xmlSchemaPSimpleTypeErr(ctxt,
6366 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6367 NULL, NULL, (xmlNodePtr) attr, NULL,
6368 "(qualified | unqualified)", val, NULL, NULL, NULL);
6369 }
6370 }
6371
6372 attr = xmlSchemaGetPropNode(node, "finalDefault");
6373 if (attr != NULL) {
6374 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6375 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6376 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6377 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6378 -1,
6379 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6380 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6381 xmlSchemaPSimpleTypeErr(ctxt,
6382 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6383 NULL, NULL, (xmlNodePtr) attr, NULL,
6384 "(#all | List of (extension | restriction | list | union))",
6385 val, NULL, NULL, NULL);
6386 }
6387 }
6388
6389 attr = xmlSchemaGetPropNode(node, "blockDefault");
6390 if (attr != NULL) {
6391 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6392 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6393 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6394 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6395 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6396 xmlSchemaPSimpleTypeErr(ctxt,
6397 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6398 NULL, NULL, (xmlNodePtr) attr, NULL,
6399 "(#all | List of (extension | restriction | substitution))",
6400 val, NULL, NULL, NULL);
6401 }
6402 }
6403}
6404
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006405/**
6406 * xmlSchemaParseSchemaTopLevel:
6407 * @ctxt: a schema validation context
6408 * @schema: the schemas
6409 * @nodes: the list of top level nodes
6410 *
6411 * Returns the internal XML Schema structure built from the resource or
6412 * NULL in case of error
6413 */
6414static void
6415xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6416 xmlSchemaPtr schema, xmlNodePtr nodes)
6417{
6418 xmlNodePtr child;
6419 xmlSchemaAnnotPtr annot;
6420
6421 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6422 return;
6423
6424 child = nodes;
6425 while ((IS_SCHEMA(child, "include")) ||
6426 (IS_SCHEMA(child, "import")) ||
6427 (IS_SCHEMA(child, "redefine")) ||
6428 (IS_SCHEMA(child, "annotation"))) {
6429 if (IS_SCHEMA(child, "annotation")) {
6430 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6431 if (schema->annot == NULL)
6432 schema->annot = annot;
6433 else
6434 xmlSchemaFreeAnnot(annot);
6435 } else if (IS_SCHEMA(child, "import")) {
6436 xmlSchemaParseImport(ctxt, schema, child);
6437 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006438 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006439 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006440 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006441 } else if (IS_SCHEMA(child, "redefine")) {
6442 TODO
6443 }
6444 child = child->next;
6445 }
6446 while (child != NULL) {
6447 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006448 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006449 child = child->next;
6450 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006451 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006452 child = child->next;
6453 } else if (IS_SCHEMA(child, "element")) {
6454 xmlSchemaParseElement(ctxt, schema, child, 1);
6455 child = child->next;
6456 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006457 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006458 child = child->next;
6459 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006460 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006461 child = child->next;
6462 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006463 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006464 child = child->next;
6465 } else if (IS_SCHEMA(child, "notation")) {
6466 xmlSchemaParseNotation(ctxt, schema, child);
6467 child = child->next;
6468 } else {
6469 xmlSchemaPErr2(ctxt, NULL, child,
6470 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006472 child->name, NULL);
6473 child = child->next;
6474 }
6475 while (IS_SCHEMA(child, "annotation")) {
6476 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6477 if (schema->annot == NULL)
6478 schema->annot = annot;
6479 else
6480 xmlSchemaFreeAnnot(annot);
6481 child = child->next;
6482 }
6483 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006484 ctxt->parentItem = NULL;
6485 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006486}
6487
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006488static xmlSchemaImportPtr
6489xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6490 xmlHashTablePtr *imports,
6491 const xmlChar *nsName)
6492{
6493 xmlSchemaImportPtr ret;
6494
6495 if (*imports == NULL) {
6496 *imports = xmlHashCreate(10);
6497 if (*imports == NULL) {
6498 xmlSchemaPCustomErr(ctxt,
6499 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6500 NULL, NULL, (xmlNodePtr) ctxt->doc,
6501 "Internal error: failed to build the import table",
6502 NULL);
6503 return (NULL);
6504 }
6505 }
6506 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6507 if (ret == NULL) {
6508 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6509 return (NULL);
6510 }
6511 memset(ret, 0, sizeof(xmlSchemaImport));
6512 if (nsName == NULL)
6513 nsName = XML_SCHEMAS_NO_NAMESPACE;
6514 xmlHashAddEntry(*imports, nsName, ret);
6515
6516 return (ret);
6517}
6518
6519static int
6520xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006521 xmlSchemaPtr schema,
6522 xmlNodePtr node,
6523 const xmlChar *nsName,
6524 const xmlChar *location,
6525 xmlDocPtr *doc,
6526 const xmlChar **targetNamespace,
6527 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006528{
6529 xmlParserCtxtPtr parserCtxt;
6530 xmlSchemaImportPtr import;
6531 const xmlChar *ns;
6532 xmlNodePtr root;
6533
6534 /*
6535 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6536 * <xsi:noNamespaceSchemaLocation>.
6537 */
6538 *doc = NULL;
6539 /*
6540 * Given that the schemaLocation [attribute] is only a hint, it is open
6541 * to applications to ignore all but the first <import> for a given
6542 * namespace, regardless of the ·actual value· of schemaLocation, but
6543 * such a strategy risks missing useful information when new
6544 * schemaLocations are offered.
6545 *
6546 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6547 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6548 * valid or not.
6549 * We will follow XSV here.
6550 */
6551 if (location == NULL) {
6552 /*
6553 * Schema Document Location Strategy:
6554 *
6555 * 3 Based on the namespace name, identify an existing schema document,
6556 * either as a resource which is an XML document or a <schema> element
6557 * information item, in some local schema repository;
6558 *
6559 * 5 Attempt to resolve the namespace name to locate such a resource.
6560 *
6561 * NOTE: Those stategies are not supported, so we will skip.
6562 */
6563 return (0);
6564 }
6565 if (nsName == NULL)
6566 ns = XML_SCHEMAS_NO_NAMESPACE;
6567 else
6568 ns = nsName;
6569
6570 import = xmlHashLookup(schema->schemasImports, ns);
6571 if (import != NULL) {
6572 /*
6573 * There was a valid resource for the specified namespace already
6574 * defined, so skip.
6575 * TODO: This might be changed someday to allow import of
6576 * components from multiple documents for a single target namespace.
6577 */
6578 return (0);
6579 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006580
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006581 /*
6582 * Schema Document Location Strategy:
6583 *
6584 * 2 Based on the location URI, identify an existing schema document,
6585 * either as a resource which is an XML document or a <schema> element
6586 * information item, in some local schema repository;
6587 *
6588 * 4 Attempt to resolve the location URI, to locate a resource on the
6589 * web which is or contains or references a <schema> element;
6590 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6591 *
6592 */
6593 if ((absolute == 0) && (node != NULL)) {
6594 xmlChar *base, *URI;
6595
6596 base = xmlNodeGetBase(node->doc, node);
6597 if (base == NULL) {
6598 URI = xmlBuildURI(location, node->doc->URL);
6599 } else {
6600 URI = xmlBuildURI(location, base);
6601 xmlFree(base);
6602 }
6603 if (URI != NULL) {
6604 location = xmlDictLookup(ctxt->dict, URI, -1);
6605 xmlFree(URI);
6606 }
6607 }
6608 parserCtxt = xmlNewParserCtxt();
6609 if (parserCtxt == NULL) {
6610 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6611 "allocating a parser context", NULL);
6612 return(-1);
6613 }
6614
6615 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6616 NULL, SCHEMAS_PARSE_OPTIONS);
6617
6618 /*
6619 * 2.1 The referent is (a fragment of) a resource which is an
6620 * XML document (see clause 1.1), which in turn corresponds to
6621 * a <schema> element information item in a well-formed information
6622 * set, which in turn corresponds to a valid schema.
6623 * TODO: What to do with the "fragment" stuff?
6624 *
6625 * 2.2 The referent is a <schema> element information item in
6626 * a well-formed information set, which in turn corresponds
6627 * to a valid schema.
6628 * NOTE: 2.2 won't apply, since only XML documents will be processed
6629 * here.
6630 */
6631 if (*doc == NULL) {
6632 xmlErrorPtr lerr;
6633 /*
6634 * It is *not* an error for the application schema reference
6635 * strategy to fail.
6636 *
6637 * If the doc is NULL and the parser error is an IO error we
6638 * will assume that the resource could not be located or accessed.
6639 *
6640 * TODO: Try to find specific error codes to react only on
6641 * localisation failures.
6642 *
6643 * TODO, FIXME: Check the spec: is a namespace added to the imported
6644 * namespaces, even if the schemaLocation did not provide
6645 * a resource? I guess so, since omitting the "schemaLocation"
6646 * attribute, imports a namespace as well.
6647 */
6648 lerr = xmlGetLastError();
6649 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6650 xmlFreeParserCtxt(parserCtxt);
6651 return(0);
6652 }
6653
6654 xmlSchemaPCustomErr(ctxt,
6655 XML_SCHEMAP_SRC_IMPORT_2_1,
6656 NULL, NULL, node,
6657 "Failed to parse the resource '%s' for import",
6658 location);
6659 xmlFreeParserCtxt(parserCtxt);
6660 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6661 }
6662 xmlFreeParserCtxt(parserCtxt);
6663
6664 root = xmlDocGetRootElement(*doc);
6665 if (root == NULL) {
6666 xmlSchemaPCustomErr(ctxt,
6667 XML_SCHEMAP_SRC_IMPORT_2_1,
6668 NULL, NULL, node,
6669 "The XML document '%s' to be imported has no document "
6670 "element", location);
6671 xmlFreeDoc(*doc);
6672 *doc = NULL;
6673 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6674 }
6675
6676 xmlSchemaCleanupDoc(ctxt, root);
6677
6678 if (!IS_SCHEMA(root, "schema")) {
6679 xmlSchemaPCustomErr(ctxt,
6680 XML_SCHEMAP_SRC_IMPORT_2_1,
6681 NULL, NULL, node,
6682 "The XML document '%s' to be imported is not a XML schema document",
6683 location);
6684 xmlFreeDoc(*doc);
6685 *doc = NULL;
6686 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6687 }
6688 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6689 /*
6690 * Schema Representation Constraint: Import Constraints and Semantics
6691 */
6692 if (nsName == NULL) {
6693 if (*targetNamespace != NULL) {
6694 xmlSchemaPCustomErr(ctxt,
6695 XML_SCHEMAP_SRC_IMPORT_3_2,
6696 NULL, NULL, node,
6697 "The XML schema to be imported is not expected "
6698 "to have a target namespace; this differs from "
6699 "its target namespace of '%s'", *targetNamespace);
6700 xmlFreeDoc(*doc);
6701 *doc = NULL;
6702 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6703 }
6704 } else {
6705 if (*targetNamespace == NULL) {
6706 xmlSchemaPCustomErr(ctxt,
6707 XML_SCHEMAP_SRC_IMPORT_3_1,
6708 NULL, NULL, node,
6709 "The XML schema to be imported is expected to have a target "
6710 "namespace of '%s'", nsName);
6711 xmlFreeDoc(*doc);
6712 *doc = NULL;
6713 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6714 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6715 xmlSchemaPCustomErrExt(ctxt,
6716 XML_SCHEMAP_SRC_IMPORT_3_1,
6717 NULL, NULL, node,
6718 "The XML schema to be imported is expected to have a "
6719 "target namespace of '%s'; this differs from "
6720 "its target namespace of '%s'",
6721 nsName, *targetNamespace, NULL);
6722 xmlFreeDoc(*doc);
6723 *doc = NULL;
6724 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6725 }
6726 }
6727
6728 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6729 if (import == NULL) {
6730 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6731 NULL, NULL, NULL,
6732 "Internal error: xmlSchemaAcquireSchemaDoc, "
6733 "failed to build import table", NULL);
6734 xmlFreeDoc(*doc);
6735 *doc = NULL;
6736 return (-1);
6737 }
6738 import->schemaLocation = location;
6739 import->doc = *doc;
6740 return (0);
6741}
William M. Brack2f2a6632004-08-20 23:09:47 +00006742
6743/**
6744 * xmlSchemaParseImport:
6745 * @ctxt: a schema validation context
6746 * @schema: the schema being built
6747 * @node: a subtree containing XML Schema informations
6748 *
6749 * parse a XML schema Import definition
6750 * *WARNING* this interface is highly subject to change
6751 *
6752 * Returns 0 in case of success, a positive error code if
6753 * not valid and -1 in case of an internal error.
6754 */
6755static int
6756xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6757 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006758{
6759 xmlNodePtr child;
6760 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006761 const xmlChar *schemaLocation = NULL;
6762 const xmlChar *targetNamespace, *oldTNS, *url;
6763 xmlAttrPtr attr;
6764 xmlDocPtr doc;
6765 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006766 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006767
6768
6769 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6770 return (-1);
6771
6772 /*
6773 * Check for illegal attributes.
6774 */
6775 attr = node->properties;
6776 while (attr != NULL) {
6777 if (attr->ns == NULL) {
6778 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6779 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6780 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6781 xmlSchemaPIllegalAttrErr(ctxt,
6782 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6783 NULL, NULL, attr);
6784 }
6785 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6786 xmlSchemaPIllegalAttrErr(ctxt,
6787 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6788 NULL, NULL, attr);
6789 }
6790 attr = attr->next;
6791 }
6792 /*
6793 * Extract and validate attributes.
6794 */
6795 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6796 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6797 &namespace) != 0) {
6798 xmlSchemaPSimpleTypeErr(ctxt,
6799 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6800 NULL, NULL, node,
6801 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6802 NULL, namespace, NULL, NULL, NULL);
6803 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6804 }
6805
6806 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6807 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6808 &schemaLocation) != 0) {
6809 xmlSchemaPSimpleTypeErr(ctxt,
6810 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6811 NULL, NULL, node,
6812 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6813 NULL, namespace, NULL, NULL, NULL);
6814 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6815 }
6816 /*
6817 * And now for the children...
6818 */
6819 child = node->children;
6820 if (IS_SCHEMA(child, "annotation")) {
6821 /*
6822 * the annotation here is simply discarded ...
6823 */
6824 child = child->next;
6825 }
6826 if (child != NULL) {
6827 xmlSchemaPContentErr(ctxt,
6828 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6829 NULL, NULL, node, child, NULL,
6830 "(annotation?)");
6831 }
6832 /*
6833 * Apply additional constraints.
6834 */
6835 if (namespace != NULL) {
6836 /*
6837 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6838 * must not match the ·actual value· of the enclosing <schema>'s
6839 * targetNamespace [attribute].
6840 */
6841 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6842 xmlSchemaPCustomErr(ctxt,
6843 XML_SCHEMAP_SRC_IMPORT_1_1,
6844 NULL, NULL, node,
6845 "The value of the attribute 'namespace' must not match "
6846 "the target namespace '%s' of the importing schema",
6847 schema->targetNamespace);
6848 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6849 }
6850 } else {
6851 /*
6852 * 1.2 If the namespace [attribute] is not present, then the enclosing
6853 * <schema> must have a targetNamespace [attribute].
6854 */
6855 if (schema->targetNamespace == NULL) {
6856 xmlSchemaPCustomErr(ctxt,
6857 XML_SCHEMAP_SRC_IMPORT_1_2,
6858 NULL, NULL, node,
6859 "The attribute 'namespace' must be existent if "
6860 "the importing schema has no target namespace",
6861 NULL);
6862 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6863 }
6864 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006865 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006866 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006867 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006868 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6869 schemaLocation, &doc, &targetNamespace, 0);
6870 if (ret != 0) {
6871 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006872 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006873 return (ret);
6874 } else if (doc != NULL) {
6875 /*
6876 * Save and reset the context & schema.
6877 */
6878 url = ctxt->URL;
6879 /* TODO: Is using the doc->URL here correct? */
6880 ctxt->URL = doc->URL;
6881 flags = schema->flags;
6882 oldTNS = schema->targetNamespace;
6883 /*
6884 * Parse the schema.
6885 */
6886 root = xmlDocGetRootElement(doc);
6887 xmlSchemaClearSchemaDefaults(schema);
6888 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6889 schema->targetNamespace = targetNamespace;
6890 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6891 /*
6892 * Restore the context & schema.
6893 */
6894 schema->flags = flags;
6895 schema->targetNamespace = oldTNS;
6896 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00006897 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006898
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006899 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00006900}
6901
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006902/**
6903 * xmlSchemaParseInclude:
6904 * @ctxt: a schema validation context
6905 * @schema: the schema being built
6906 * @node: a subtree containing XML Schema informations
6907 *
6908 * parse a XML schema Include definition
6909 *
William M. Bracke7091952004-05-11 15:09:58 +00006910 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006911 * 1 in case of success.
6912 */
6913static int
6914xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6915 xmlNodePtr node)
6916{
6917 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006918 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006919 xmlDocPtr doc;
6920 xmlNodePtr root;
6921 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006922 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006923 xmlAttrPtr attr;
6924 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006925
6926
6927 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6928 return (-1);
6929
6930 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006931 * Check for illegal attributes.
6932 */
6933 attr = node->properties;
6934 while (attr != NULL) {
6935 if (attr->ns == NULL) {
6936 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6937 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6938 xmlSchemaPIllegalAttrErr(ctxt,
6939 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6940 NULL, NULL, attr);
6941 }
6942 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6943 xmlSchemaPIllegalAttrErr(ctxt,
6944 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6945 NULL, NULL, attr);
6946 }
6947 attr = attr->next;
6948 }
6949 /*
6950 * Extract and validate attributes.
6951 */
6952 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006953 * Preliminary step, extract the URI-Reference for the include and
6954 * make an URI from the base.
6955 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006956 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6957 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006958 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006959 xmlChar *uri = NULL;
6960
6961 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6962 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6963 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006964 base = xmlNodeGetBase(node->doc, node);
6965 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006966 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006967 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006968 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006969 xmlFree(base);
6970 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006971 if (uri != NULL) {
6972 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6973 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006974 }
6975 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006976 xmlSchemaPMissingAttrErr(ctxt,
6977 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6978 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006979 return (-1);
6980 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006981 /*
6982 * And now for the children...
6983 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006984 child = node->children;
6985 while (IS_SCHEMA(child, "annotation")) {
6986 /*
6987 * the annotations here are simply discarded ...
6988 */
6989 child = child->next;
6990 }
6991 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006992 xmlSchemaPContentErr(ctxt,
6993 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6994 NULL, NULL, node, child, NULL,
6995 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006996 }
6997
6998 /*
6999 * First step is to parse the input document into an DOM/Infoset
7000 */
7001 doc = xmlReadFile((const char *) schemaLocation, NULL,
7002 SCHEMAS_PARSE_OPTIONS);
7003 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007004 /*
7005 * TODO: It is not an error for the ·actual value· of the
7006 * schemaLocation [attribute] to fail to resolve it all, in which
7007 * case no corresponding inclusion is performed.
7008 * So do we need a warning report here?
7009 */
7010 xmlSchemaPCustomErr(ctxt,
7011 XML_SCHEMAP_FAILED_LOAD,
7012 NULL, NULL, node,
7013 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007014 return(-1);
7015 }
7016
7017 /*
7018 * Then extract the root of the schema
7019 */
7020 root = xmlDocGetRootElement(doc);
7021 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007022 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007023 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007024 NULL, NULL, node,
7025 "The included document '%s' has no document "
7026 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007027 xmlFreeDoc(doc);
7028 return (-1);
7029 }
7030
7031 /*
7032 * Remove all the blank text nodes
7033 */
7034 xmlSchemaCleanupDoc(ctxt, root);
7035
7036 /*
7037 * Check the schemas top level element
7038 */
7039 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007040 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007041 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007042 NULL, NULL, node,
7043 "The document '%s' to be included is not a schema document",
7044 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007045 xmlFreeDoc(doc);
7046 return (-1);
7047 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007048
William M. Brack2f2a6632004-08-20 23:09:47 +00007049 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007050 /*
7051 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7052 * value· is identical to the ·actual value· of the targetNamespace
7053 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7054 */
7055 if (targetNamespace != NULL) {
7056 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007057 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007058 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007059 NULL, NULL, node,
7060 "The target namespace of the included schema "
7061 "'%s' has to be absent, since the including schema "
7062 "has no target namespace",
7063 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007064 xmlFreeDoc(doc);
7065 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007066 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7067 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007068 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007069 NULL, NULL, node,
7070 "The target namespace '%s' of the included schema '%s' "
7071 "differs from '%s' of the including schema",
7072 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007073 xmlFreeDoc(doc);
7074 return (-1);
7075 }
7076 } else if (schema->targetNamespace != NULL) {
7077 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7078 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7079 } else
7080 wasConvertingNs = 1;
7081 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007082 /*
7083 * register the include
7084 */
7085 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7086 if (include == NULL) {
7087 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7088 xmlFreeDoc(doc);
7089 return (-1);
7090 }
7091
7092 memset(include, 0, sizeof(xmlSchemaInclude));
7093 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7094 include->doc = doc;
7095 include->next = schema->includes;
7096 schema->includes = include;
7097
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007098 /*
7099 * parse the declarations in the included file like if they
7100 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007101 */
7102 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007103 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007104 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007105 /*
7106 * The default values ("blockDefault", "elementFormDefault", etc.)
7107 * are set to the values of the included schema and restored afterwards.
7108 */
7109 saveFlags = schema->flags;
7110 xmlSchemaClearSchemaDefaults(schema);
7111 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007112 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007113 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007114 /*
7115 * Remove the converting flag.
7116 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007117 if ((wasConvertingNs == 0) &&
7118 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007119 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007120 return (1);
7121}
7122
7123/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007124 * xmlSchemaParseChoice:
7125 * @ctxt: a schema validation context
7126 * @schema: the schema being built
7127 * @node: a subtree containing XML Schema informations
7128 *
7129 * parse a XML schema Choice definition
7130 * *WARNING* this interface is highly subject to change
7131 *
William M. Bracke7091952004-05-11 15:09:58 +00007132 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007133 * 1 in case of success.
7134 */
7135static xmlSchemaTypePtr
7136xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007137 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007138{
7139 xmlSchemaTypePtr type, subtype, last = NULL;
7140 xmlNodePtr child = NULL;
7141 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007142 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007143 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007144
7145 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7146 return (NULL);
7147
7148
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007149 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007150 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007151 if (type == NULL)
7152 return (NULL);
7153 type->node = node;
7154 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007155 /*
7156 * Check for illegal attributes.
7157 */
7158 attr = node->properties;
7159 while (attr != NULL) {
7160 if (attr->ns == NULL) {
7161 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7162 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7163 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7164 xmlSchemaPIllegalAttrErr(ctxt,
7165 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7166 NULL, type, attr);
7167 }
7168 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7169 xmlSchemaPIllegalAttrErr(ctxt,
7170 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7171 NULL, type, attr);
7172 }
7173 attr = attr->next;
7174 }
7175 /*
7176 * Extract and validate attributes.
7177 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007178 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007179 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7180 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7181 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007182 /*
7183 * And now for the children...
7184 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007185 oldcontainer = ctxt->container;
7186 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007187 child = node->children;
7188 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007189 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7190 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007191 }
7192 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007193 (IS_SCHEMA(child, "group")) ||
7194 (IS_SCHEMA(child, "any")) ||
7195 (IS_SCHEMA(child, "choice")) ||
7196 (IS_SCHEMA(child, "sequence"))) {
7197 subtype = NULL;
7198 if (IS_SCHEMA(child, "element")) {
7199 subtype = (xmlSchemaTypePtr)
7200 xmlSchemaParseElement(ctxt, schema, child, 0);
7201 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007202 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007203 } else if (IS_SCHEMA(child, "any")) {
7204 subtype = xmlSchemaParseAny(ctxt, schema, child);
7205 } else if (IS_SCHEMA(child, "sequence")) {
7206 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7207 } else if (IS_SCHEMA(child, "choice")) {
7208 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7209 }
7210 if (subtype != NULL) {
7211 if (last == NULL) {
7212 type->subtypes = subtype;
7213 last = subtype;
7214 } else {
7215 last->next = subtype;
7216 last = subtype;
7217 }
7218 last->next = NULL;
7219 }
7220 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007221 }
7222 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007223 /* TODO: error code. */
7224 xmlSchemaPContentErr(ctxt,
7225 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7226 NULL, type, node, child, NULL,
7227 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007228 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007229 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007230 return (type);
7231}
7232
7233/**
7234 * xmlSchemaParseSequence:
7235 * @ctxt: a schema validation context
7236 * @schema: the schema being built
7237 * @node: a subtree containing XML Schema informations
7238 *
7239 * parse a XML schema Sequence definition
7240 * *WARNING* this interface is highly subject to change
7241 *
William M. Bracke7091952004-05-11 15:09:58 +00007242 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007243 * 1 in case of success.
7244 */
7245static xmlSchemaTypePtr
7246xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007247 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007248{
7249 xmlSchemaTypePtr type, subtype, last = NULL;
7250 xmlNodePtr child = NULL;
7251 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007252 xmlAttrPtr attr;
7253 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007254
7255 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7256 return (NULL);
7257
William M. Brack2f2a6632004-08-20 23:09:47 +00007258 oldcontainer = ctxt->container;
7259 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7260 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007261 if (type == NULL)
7262 return (NULL);
7263 type->node = node;
7264 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007265 /*
7266 * Check for illegal attributes.
7267 */
7268 attr = node->properties;
7269 while (attr != NULL) {
7270 if (attr->ns == NULL) {
7271 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7272 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7273 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7274 xmlSchemaPIllegalAttrErr(ctxt,
7275 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7276 NULL, type, attr);
7277 }
7278 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7279 xmlSchemaPIllegalAttrErr(ctxt,
7280 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7281 NULL, type, attr);
7282 }
7283 attr = attr->next;
7284 }
7285 /*
7286 * Extract and validate attributes.
7287 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007288 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007289 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7290 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7291 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007292 /*
7293 * And now for the children...
7294 */
7295 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007296 child = node->children;
7297 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007298 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007300 }
7301 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007302 (IS_SCHEMA(child, "group")) ||
7303 (IS_SCHEMA(child, "any")) ||
7304 (IS_SCHEMA(child, "choice")) ||
7305 (IS_SCHEMA(child, "sequence"))) {
7306 subtype = NULL;
7307 if (IS_SCHEMA(child, "element")) {
7308 subtype = (xmlSchemaTypePtr)
7309 xmlSchemaParseElement(ctxt, schema, child, 0);
7310 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007311 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007312 } else if (IS_SCHEMA(child, "any")) {
7313 subtype = xmlSchemaParseAny(ctxt, schema, child);
7314 } else if (IS_SCHEMA(child, "choice")) {
7315 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7316 } else if (IS_SCHEMA(child, "sequence")) {
7317 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7318 }
7319 if (subtype != NULL) {
7320 if (last == NULL) {
7321 type->subtypes = subtype;
7322 last = subtype;
7323 } else {
7324 last->next = subtype;
7325 last = subtype;
7326 }
7327 last->next = NULL;
7328 }
7329 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007330 }
7331 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007332 xmlSchemaPContentErr(ctxt,
7333 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7334 NULL, type, node, child, NULL,
7335 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007336 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007337 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007338
7339 return (type);
7340}
7341
7342/**
7343 * xmlSchemaParseRestriction:
7344 * @ctxt: a schema validation context
7345 * @schema: the schema being built
7346 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007347 *
7348 * parse a XML schema Restriction definition
7349 * *WARNING* this interface is highly subject to change
7350 *
7351 * Returns the type definition or NULL in case of error
7352 */
7353static xmlSchemaTypePtr
7354xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007355 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007356{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007357 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007358 xmlNodePtr child = NULL;
7359 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007360 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007361 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007362
7363 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7364 return (NULL);
7365
7366 oldcontainer = ctxt->container;
7367
William M. Brack2f2a6632004-08-20 23:09:47 +00007368 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7369 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007370 if (type == NULL)
7371 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007372 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007373 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007374 /*
7375 * Check for illegal attributes.
7376 */
7377 attr = node->properties;
7378 while (attr != NULL) {
7379 if (attr->ns == NULL) {
7380 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7381 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7382 xmlSchemaPIllegalAttrErr(ctxt,
7383 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7384 NULL, type, attr);
7385 }
7386 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7387 xmlSchemaPIllegalAttrErr(ctxt,
7388 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7389 NULL, type, attr);
7390 }
7391 attr = attr->next;
7392 }
7393 /*
7394 * Extract and validate attributes.
7395 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007396 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007397 /*
7398 * Attribute "base".
7399 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007400 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007401 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007402 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7403 /* TODO: Think about the error code. */
7404 xmlSchemaPMissingAttrErr(ctxt,
7405 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7406 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007407 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007408 /*
7409 * And now for the children...
7410 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007411 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007412 child = node->children;
7413 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007414 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7415 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007416 }
7417 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007418 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7419 if (IS_SCHEMA(child, "all")) {
7420 subtype = (xmlSchemaTypePtr)
7421 xmlSchemaParseAll(ctxt, schema, child);
7422 child = child->next;
7423 type->subtypes = subtype;
7424 } else if (IS_SCHEMA(child, "choice")) {
7425 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7426 child = child->next;
7427 type->subtypes = subtype;
7428 } else if (IS_SCHEMA(child, "sequence")) {
7429 subtype = (xmlSchemaTypePtr)
7430 xmlSchemaParseSequence(ctxt, schema, child);
7431 child = child->next;
7432 type->subtypes = subtype;
7433 } else if (IS_SCHEMA(child, "group")) {
7434 subtype = (xmlSchemaTypePtr)
7435 xmlSchemaParseGroup(ctxt, schema, child, 0);
7436 child = child->next;
7437 type->subtypes = subtype;
7438 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007439 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7440 if (IS_SCHEMA(child, "simpleType")) {
7441 if (type->base != NULL) {
7442 /*
7443 * src-restriction-base-or-simpleType
7444 * Either the base [attribute] or the simpleType [child] of the
7445 * <restriction> element must be present, but not both.
7446 */
7447 xmlSchemaPContentErr(ctxt,
7448 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7449 NULL, NULL, type->node, child,
7450 "The attribute 'base' and the <simpleType> child are "
7451 "mutually exclusive", NULL);
7452 } else {
7453 subtype = (xmlSchemaTypePtr)
7454 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7455 type->baseType = subtype;
7456 }
7457 child = child->next;
7458 }
7459 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007460 if (IS_SCHEMA(child, "simpleType")) {
7461 subtype = (xmlSchemaTypePtr)
7462 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007463 type->subtypes = subtype;
7464 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007465 }
7466 }
7467 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7468 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7469 xmlSchemaFacetPtr facet, lastfacet = NULL;
7470
Daniel Veillard01fa6152004-06-29 17:04:39 +00007471 /*
7472 * Add the facets to the parent simpleType/complexType.
7473 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007474 /*
7475 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7476 * Simple Type Definition Schema Representation Constraint:
7477 * *Single Facet Value*
7478 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007479 while ((IS_SCHEMA(child, "minInclusive")) ||
7480 (IS_SCHEMA(child, "minExclusive")) ||
7481 (IS_SCHEMA(child, "maxInclusive")) ||
7482 (IS_SCHEMA(child, "maxExclusive")) ||
7483 (IS_SCHEMA(child, "totalDigits")) ||
7484 (IS_SCHEMA(child, "fractionDigits")) ||
7485 (IS_SCHEMA(child, "pattern")) ||
7486 (IS_SCHEMA(child, "enumeration")) ||
7487 (IS_SCHEMA(child, "whiteSpace")) ||
7488 (IS_SCHEMA(child, "length")) ||
7489 (IS_SCHEMA(child, "maxLength")) ||
7490 (IS_SCHEMA(child, "minLength"))) {
7491 facet = xmlSchemaParseFacet(ctxt, schema, child);
7492 if (facet != NULL) {
7493 if (lastfacet == NULL)
7494 ctxt->ctxtType->facets = facet;
7495 else
7496 lastfacet->next = facet;
7497 lastfacet = facet;
7498 lastfacet->next = NULL;
7499 }
7500 child = child->next;
7501 }
7502 /*
7503 * Create links for derivation and validation.
7504 */
7505 if (lastfacet != NULL) {
7506 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7507
7508 facet = ctxt->ctxtType->facets;
7509 do {
7510 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7511 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007512 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007513 xmlFree(facetLink);
7514 return (NULL);
7515 }
7516 facetLink->facet = facet;
7517 facetLink->next = NULL;
7518 if (lastFacetLink == NULL)
7519 ctxt->ctxtType->facetSet = facetLink;
7520 else
7521 lastFacetLink->next = facetLink;
7522 lastFacetLink = facetLink;
7523 facet = facet->next;
7524 } while (facet != NULL);
7525 }
7526 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007527 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7528 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7529 if (IS_SCHEMA(child, "anyAttribute")) {
7530 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7531 child = child->next;
7532 }
7533 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007534 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007535 /* TODO: Think about the error code. */
7536 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7537 xmlSchemaPContentErr(ctxt,
7538 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7539 NULL, type, node, child, NULL,
7540 "annotation?, (group | all | choice | sequence)?, "
7541 "((attribute | attributeGroup)*, anyAttribute?))");
7542 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7543 xmlSchemaPContentErr(ctxt,
7544 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7545 NULL, type, node, child, NULL,
7546 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7547 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7548 "length | minLength | maxLength | enumeration | whiteSpace | "
7549 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7550 } else {
7551 /* Simple type */
7552 xmlSchemaPContentErr(ctxt,
7553 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7554 NULL, type, node, child, NULL,
7555 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7556 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7557 "length | minLength | maxLength | enumeration | whiteSpace | "
7558 "pattern)*))");
7559 }
7560 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007561 ctxt->container = oldcontainer;
7562 return (type);
7563}
7564
7565/**
7566 * xmlSchemaParseExtension:
7567 * @ctxt: a schema validation context
7568 * @schema: the schema being built
7569 * @node: a subtree containing XML Schema informations
7570 *
7571 * parse a XML schema Extension definition
7572 * *WARNING* this interface is highly subject to change
7573 *
7574 * Returns the type definition or NULL in case of error
7575 */
7576static xmlSchemaTypePtr
7577xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007578 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007579{
7580 xmlSchemaTypePtr type, subtype;
7581 xmlNodePtr child = NULL;
7582 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007583 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007584
7585 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7586 return (NULL);
7587
7588 oldcontainer = ctxt->container;
7589
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007590 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007591 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007592 if (type == NULL)
7593 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007594 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007595 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007596 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007597 ctxt->container = name;
7598
7599 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7600 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007601 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 "<extension>: The attribute \"base\" is missing.\n",
7603 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007604 }
7605 child = node->children;
7606 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007607 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7608 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007609 }
7610 subtype = NULL;
7611
7612 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007613 subtype = xmlSchemaParseAll(ctxt, schema, child);
7614 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007615 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007616 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7617 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007618 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007619 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7620 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007621 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007622 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007623 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007624 }
7625 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007626 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007627 if ((ctxt->ctxtType != NULL) &&
7628 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7629 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7630 if (IS_SCHEMA(child, "anyAttribute")) {
7631 ctxt->ctxtType->attributeWildcard =
7632 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7633 child = child->next;
7634 }
7635 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007636 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007637 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007638 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7639 "<extension> has unexpected content.\n", type->name,
7640 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007641 }
7642 ctxt->container = oldcontainer;
7643 return (type);
7644}
7645
7646/**
7647 * xmlSchemaParseSimpleContent:
7648 * @ctxt: a schema validation context
7649 * @schema: the schema being built
7650 * @node: a subtree containing XML Schema informations
7651 *
7652 * parse a XML schema SimpleContent definition
7653 * *WARNING* this interface is highly subject to change
7654 *
7655 * Returns the type definition or NULL in case of error
7656 */
7657static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007658xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7659 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007660{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007661 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007662 xmlNodePtr child = NULL;
7663 xmlChar name[30];
7664
7665 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7666 return (NULL);
7667
William M. Bracke7091952004-05-11 15:09:58 +00007668 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007669 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007670 if (type == NULL)
7671 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007672 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007673 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007674 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007675
7676 child = node->children;
7677 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007678 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7679 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007680 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007681 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007682 ctxt->parentItem = type;
7683 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007684 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007685 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007686 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007687 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007688 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007689 subtype = (xmlSchemaTypePtr)
7690 xmlSchemaParseExtension(ctxt, schema, child);
7691 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007692 }
7693 type->subtypes = subtype;
7694 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007695 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007696 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7697 "<simpleContent> has unexpected content.\n",
7698 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007699 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007700 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007701 return (type);
7702}
7703
7704/**
7705 * xmlSchemaParseComplexContent:
7706 * @ctxt: a schema validation context
7707 * @schema: the schema being built
7708 * @node: a subtree containing XML Schema informations
7709 *
7710 * parse a XML schema ComplexContent definition
7711 * *WARNING* this interface is highly subject to change
7712 *
7713 * Returns the type definition or NULL in case of error
7714 */
7715static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007716xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7717 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007718{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007719 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007720 xmlNodePtr child = NULL;
7721 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007722 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007723
7724 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7725 return (NULL);
7726
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007727 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007728 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007729 if (type == NULL)
7730 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007731 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007732 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007733 /*
7734 * Check for illegal attributes.
7735 */
7736 attr = node->properties;
7737 while (attr != NULL) {
7738 if (attr->ns == NULL) {
7739 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7740 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7741 {
7742 xmlSchemaPIllegalAttrErr(ctxt,
7743 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7744 NULL, NULL, attr);
7745 }
7746 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7747 xmlSchemaPIllegalAttrErr(ctxt,
7748 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7749 NULL, NULL, attr);
7750 }
7751 attr = attr->next;
7752 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007753 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007754 /*
7755 * Handle attribute 'mixed'.
7756 */
7757 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7758 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7759 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7760 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007761 child = node->children;
7762 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007763 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7764 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007765 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007766 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007767 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007768 subtype = NULL;
7769 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007770 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007771 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007772 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007773 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007774 subtype = (xmlSchemaTypePtr)
7775 xmlSchemaParseExtension(ctxt, schema, child);
7776 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007777 }
7778 type->subtypes = subtype;
7779 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007780 xmlSchemaPContentErr(ctxt,
7781 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7782 NULL, NULL, node, child,
7783 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007784 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007785 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007786 return (type);
7787}
7788
7789/**
7790 * xmlSchemaParseComplexType:
7791 * @ctxt: a schema validation context
7792 * @schema: the schema being built
7793 * @node: a subtree containing XML Schema informations
7794 *
7795 * parse a XML schema Complex Type definition
7796 * *WARNING* this interface is highly subject to change
7797 *
7798 * Returns the type definition or NULL in case of error
7799 */
7800static xmlSchemaTypePtr
7801xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007802 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007803{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007804 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007805 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007806 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007807 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007808 xmlAttrPtr attr;
7809 const xmlChar *attrValue;
7810 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007811 char buf[40];
7812
Daniel Veillard4255d502002-04-16 15:50:10 +00007813
7814 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7815 return (NULL);
7816
Daniel Veillard01fa6152004-06-29 17:04:39 +00007817 ctxtType = ctxt->ctxtType;
7818
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007819 if (topLevel) {
7820 attr = xmlSchemaGetPropNode(node, "name");
7821 if (attr == NULL) {
7822 xmlSchemaPMissingAttrErr(ctxt,
7823 XML_SCHEMAP_S4S_ATTR_MISSING,
7824 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7825 "name", NULL);
7826 return (NULL);
7827 } else if (xmlSchemaPValAttrNode(ctxt,
7828 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7829 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7830 return (NULL);
7831 }
7832 }
7833
7834 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007835 /*
7836 * Parse as local complex type definition.
7837 */
7838 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7839 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7840 if (type == NULL)
7841 return (NULL);
7842 name = (const xmlChar *) buf;
7843 type->node = node;
7844 type->type = XML_SCHEMA_TYPE_COMPLEX;
7845 /*
7846 * TODO: We need the target namespace.
7847 */
7848 } else {
7849 /*
7850 * Parse as global complex type definition.
7851 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007852 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007853 if (type == NULL)
7854 return (NULL);
7855 type->node = node;
7856 type->type = XML_SCHEMA_TYPE_COMPLEX;
7857 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7858 /*
7859 * Set defaults.
7860 */
7861 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7862 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
7863 }
7864 /*
7865 * Handle attributes.
7866 */
7867 attr = node->properties;
7868 while (attr != NULL) {
7869 if (attr->ns == NULL) {
7870 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7871 /*
7872 * Attribute "id".
7873 */
7874 type->id = xmlSchemaGetProp(ctxt, node, "id");
7875 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
7876 /*
7877 * Attribute "mixed".
7878 */
7879 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7880 (xmlNodePtr) attr))
7881 type->flags |= XML_SCHEMAS_TYPE_MIXED;
7882 } else if (topLevel) {
7883 /*
7884 * Attributes of global complex type definitions.
7885 */
7886 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7887 /* Pass. */
7888 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
7889 /*
7890 * Attribute "abstract".
7891 */
7892 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7893 (xmlNodePtr) attr))
7894 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
7895 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
7896 /*
7897 * Attribute "final".
7898 */
7899 attrValue = xmlSchemaGetNodeContent(ctxt,
7900 (xmlNodePtr) attr);
7901 if (xmlSchemaPValAttrBlockFinal(attrValue,
7902 &(type->flags),
7903 -1,
7904 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
7905 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
7906 -1, -1, -1) != 0)
7907 {
7908 xmlSchemaPSimpleTypeErr(ctxt,
7909 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7910 &des, type, (xmlNodePtr) attr,
7911 NULL,
7912 "(#all | List of (extension | restriction))",
7913 attrValue, NULL, NULL, NULL);
7914 }
7915 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
7916 /*
7917 * Attribute "block".
7918 */
7919 attrValue = xmlSchemaGetNodeContent(ctxt,
7920 (xmlNodePtr) attr);
7921 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7922 -1,
7923 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
7924 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
7925 -1, -1, -1) != 0) {
7926 xmlSchemaPSimpleTypeErr(ctxt,
7927 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7928 &des, type, (xmlNodePtr) attr,
7929 NULL,
7930 "(#all | List of (extension | restriction)) ",
7931 attrValue, NULL, NULL, NULL);
7932 }
7933 } else {
7934 xmlSchemaPIllegalAttrErr(ctxt,
7935 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7936 &des, type, attr);
7937 }
7938 } else {
7939 xmlSchemaPIllegalAttrErr(ctxt,
7940 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7941 &des, type, attr);
7942 }
7943 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7944 xmlSchemaPIllegalAttrErr(ctxt,
7945 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7946 &des, type, attr);
7947 }
7948 attr = attr->next;
7949 }
7950 /*
7951 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007952 * This will be only changed if a complex type
7953 * inherits an attribute wildcard from a base type.
7954 */
7955 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007956 /*
7957 * And now for the children...
7958 */
7959 oldcontainer = ctxt->container;
7960 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007961 child = node->children;
7962 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007963 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7964 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007965 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007966 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007967 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007968 /*
7969 * 3.4.3 : 2.2
7970 * Specifying mixed='true' when the <simpleContent>
7971 * alternative is chosen has no effect
7972 */
William M. Bracke7091952004-05-11 15:09:58 +00007973 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7974 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007975 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7976 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007977 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007978 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7979 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007980 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007981 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007982 /*
7983 * Parse model groups.
7984 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007985 if (IS_SCHEMA(child, "all")) {
7986 subtype = xmlSchemaParseAll(ctxt, schema, child);
7987 child = child->next;
7988 } else if (IS_SCHEMA(child, "choice")) {
7989 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7990 child = child->next;
7991 } else if (IS_SCHEMA(child, "sequence")) {
7992 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7993 child = child->next;
7994 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007995 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007996 child = child->next;
7997 }
7998 if (subtype != NULL)
7999 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008000 /*
8001 * Parse attribute decls/refs.
8002 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008003 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008004 /*
8005 * Parse attribute wildcard.
8006 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008007 if (IS_SCHEMA(child, "anyAttribute")) {
8008 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8009 child = child->next;
8010 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008011 }
8012 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008013 xmlSchemaPContentErr(ctxt,
8014 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8015 &des, type, node, child,
8016 NULL, "(annotation?, (simpleContent | complexContent | "
8017 "((group | all | choice | sequence)?, ((attribute | "
8018 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008019 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008020 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008021 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008022 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008023 return (type);
8024}
8025
Daniel Veillard4255d502002-04-16 15:50:10 +00008026/**
8027 * xmlSchemaParseSchema:
8028 * @ctxt: a schema validation context
8029 * @node: a subtree containing XML Schema informations
8030 *
8031 * parse a XML schema definition from a node set
8032 * *WARNING* this interface is highly subject to change
8033 *
8034 * Returns the internal XML Schema structure built from the resource or
8035 * NULL in case of error
8036 */
8037static xmlSchemaPtr
8038xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8039{
8040 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008041 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008042 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008043 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008044
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008045 /*
8046 * This one is called by xmlSchemaParse only and is used if
8047 * the schema to be parsed was specified via the API; i.e. not
8048 * automatically by the validated instance document.
8049 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008050 if ((ctxt == NULL) || (node == NULL))
8051 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008052 nberrors = ctxt->nberrors;
8053 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008054 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008055 xmlSchemaImportPtr import;
8056
Daniel Veillard4255d502002-04-16 15:50:10 +00008057 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008058 if (schema == NULL)
8059 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008060 /*
8061 * Disable build of list of items.
8062 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008063 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8064 if (attr != NULL) {
8065 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8066 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8067 /*
8068 * TODO: Should we proceed with an invalid target namespace?
8069 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008070 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8071 } else {
8072 schema->targetNamespace = NULL;
8073 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008074 /*
8075 * Add the current ns name and location to the import table;
8076 * this is needed to have a consistent mechanism, regardless
8077 * if all schemata are constructed dynamically fired by the
8078 * instance or if the schema to be used was specified via
8079 * the API.
8080 */
8081 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8082 schema->targetNamespace);
8083 if (import == NULL) {
8084 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8085 NULL, NULL, (xmlNodePtr) ctxt->doc,
8086 "Internal error: xmlSchemaParseSchema, "
8087 "failed to add an import entry", NULL);
8088 xmlSchemaFree(schema);
8089 schema = NULL;
8090 return (NULL);
8091 }
8092 import->schemaLocation = ctxt->URL;
8093 /*
8094 * NOTE: We won't set the doc here, otherwise it will be freed
8095 * if the import struct is freed.
8096 * import->doc = ctxt->doc;
8097 */
8098
Daniel Veillardc0826a72004-08-10 14:17:33 +00008099 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008100 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008101 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8102 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8103
William M. Brack2f2a6632004-08-20 23:09:47 +00008104 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008105 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8106 } else {
8107 xmlDocPtr doc;
8108
8109 doc = node->doc;
8110
8111 if ((doc != NULL) && (doc->URL != NULL)) {
8112 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8113 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008114 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008115 } else {
8116 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8117 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008118 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008119 }
8120 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008121 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008122 if (ctxt->nberrors != 0) {
8123 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008124 xmlSchemaFree(schema);
8125 schema = NULL;
8126 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008127 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008128 if (schema != NULL)
8129 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008130 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008131#ifdef DEBUG
8132 if (schema == NULL)
8133 xmlGenericError(xmlGenericErrorContext,
8134 "xmlSchemaParse() failed\n");
8135#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008136 return (schema);
8137}
8138
8139/************************************************************************
8140 * *
8141 * Validating using Schemas *
8142 * *
8143 ************************************************************************/
8144
8145/************************************************************************
8146 * *
8147 * Reading/Writing Schemas *
8148 * *
8149 ************************************************************************/
8150
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008151#if 0 /* Will be enabled if it is clear what options are needed. */
8152/**
8153 * xmlSchemaParserCtxtSetOptions:
8154 * @ctxt: a schema parser context
8155 * @options: a combination of xmlSchemaParserOption
8156 *
8157 * Sets the options to be used during the parse.
8158 *
8159 * Returns 0 in case of success, -1 in case of an
8160 * API error.
8161 */
8162static int
8163xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8164 int options)
8165
8166{
8167 int i;
8168
8169 if (ctxt == NULL)
8170 return (-1);
8171 /*
8172 * WARNING: Change the start value if adding to the
8173 * xmlSchemaParseOption.
8174 */
8175 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8176 if (options & 1<<i) {
8177 return (-1);
8178 }
8179 }
8180 ctxt->options = options;
8181 return (0);
8182}
8183
8184/**
8185 * xmlSchemaValidCtxtGetOptions:
8186 * @ctxt: a schema parser context
8187 *
8188 * Returns the option combination of the parser context.
8189 */
8190static int
8191xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8192
8193{
8194 if (ctxt == NULL)
8195 return (-1);
8196 else
8197 return (ctxt->options);
8198}
8199
8200 void *curItems; /* used for dynamic addition of schemata */
8201 int nbCurItems; /* used for dynamic addition of schemata */
8202 int sizeCurItems; /* used for dynamic addition of schemata */
8203
8204#endif
8205
Daniel Veillard4255d502002-04-16 15:50:10 +00008206/**
8207 * xmlSchemaNewParserCtxt:
8208 * @URL: the location of the schema
8209 *
8210 * Create an XML Schemas parse context for that file/resource expected
8211 * to contain an XML Schemas file.
8212 *
8213 * Returns the parser context or NULL in case of error
8214 */
8215xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008216xmlSchemaNewParserCtxt(const char *URL)
8217{
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 xmlSchemaParserCtxtPtr ret;
8219
8220 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008221 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008222
8223 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8224 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008225 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008226 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008227 return (NULL);
8228 }
8229 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008230 ret->dict = xmlDictCreate();
8231 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008232 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008233 return (ret);
8234}
8235
8236/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008237 * xmlSchemaNewParserCtxtUseDict:
8238 * @URL: the location of the schema
8239 * @dict: the dictionary to be used
8240 *
8241 * Create an XML Schemas parse context for that file/resource expected
8242 * to contain an XML Schemas file.
8243 *
8244 * Returns the parser context or NULL in case of error
8245 */
8246static xmlSchemaParserCtxtPtr
8247xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8248{
8249 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008250 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008251 if (URL == NULL)
8252 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008253 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008254
8255 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8256 if (ret == NULL) {
8257 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8258 NULL);
8259 return (NULL);
8260 }
8261 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8262 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008263 xmlDictReference(dict);
8264 if (URL != NULL)
8265 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008266 ret->includes = 0;
8267 return (ret);
8268}
8269
8270
8271/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008272 * xmlSchemaNewMemParserCtxt:
8273 * @buffer: a pointer to a char array containing the schemas
8274 * @size: the size of the array
8275 *
8276 * Create an XML Schemas parse context for that memory buffer expected
8277 * to contain an XML Schemas file.
8278 *
8279 * Returns the parser context or NULL in case of error
8280 */
8281xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008282xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8283{
Daniel Veillard6045c902002-10-09 21:13:59 +00008284 xmlSchemaParserCtxtPtr ret;
8285
8286 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008287 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008288
8289 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8290 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008291 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008292 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008293 return (NULL);
8294 }
8295 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8296 ret->buffer = buffer;
8297 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008298 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008299 return (ret);
8300}
8301
8302/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008303 * xmlSchemaNewDocParserCtxt:
8304 * @doc: a preparsed document tree
8305 *
8306 * Create an XML Schemas parse context for that document.
8307 * NB. The document may be modified during the parsing process.
8308 *
8309 * Returns the parser context or NULL in case of error
8310 */
8311xmlSchemaParserCtxtPtr
8312xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8313{
8314 xmlSchemaParserCtxtPtr ret;
8315
8316 if (doc == NULL)
8317 return (NULL);
8318
8319 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8320 if (ret == NULL) {
8321 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8322 NULL);
8323 return (NULL);
8324 }
8325 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8326 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008327 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008328 /* The application has responsibility for the document */
8329 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008330
8331 return (ret);
8332}
8333
8334/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008335 * xmlSchemaFreeParserCtxt:
8336 * @ctxt: the schema parser context
8337 *
8338 * Free the resources associated to the schema parser context
8339 */
8340void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008341xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8342{
Daniel Veillard4255d502002-04-16 15:50:10 +00008343 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008344 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008345 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008346 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008347 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008348 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008349 xmlFree(ctxt->assemble);
8350 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008351 if (ctxt->vctxt != NULL) {
8352 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8353 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008354 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008355 xmlFree(ctxt);
8356}
8357
8358/************************************************************************
8359 * *
8360 * Building the content models *
8361 * *
8362 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008363
Daniel Veillard4255d502002-04-16 15:50:10 +00008364/**
8365 * xmlSchemaBuildAContentModel:
8366 * @type: the schema type definition
8367 * @ctxt: the schema parser context
8368 * @name: the element name whose content is being built
8369 *
8370 * Generate the automata sequence needed for that type
8371 */
8372static void
8373xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008374 xmlSchemaParserCtxtPtr ctxt,
8375 const xmlChar * name)
8376{
Daniel Veillard4255d502002-04-16 15:50:10 +00008377 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008378 xmlGenericError(xmlGenericErrorContext,
8379 "Found unexpected type = NULL in %s content model\n",
8380 name);
8381 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008382 }
8383 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008384 case XML_SCHEMA_TYPE_ANY: {
8385 xmlAutomataStatePtr start, end;
8386 xmlSchemaWildcardPtr wild;
8387 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008388
Daniel Veillardc0826a72004-08-10 14:17:33 +00008389 wild = type->attributeWildcard;
8390
8391 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008392 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008393 "Internal error: xmlSchemaBuildAContentModel, "
8394 "no wildcard on xsd:any.\n", NULL, NULL);
8395 return;
8396 }
8397
8398 start = ctxt->state;
8399 end = xmlAutomataNewState(ctxt->am);
8400
8401 if (type->maxOccurs == 1) {
8402 if (wild->any == 1) {
8403 /*
8404 * We need to add both transitions:
8405 *
8406 * 1. the {"*", "*"} for elements in a namespace.
8407 */
8408 ctxt->state =
8409 xmlAutomataNewTransition2(ctxt->am,
8410 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8411 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8412 /*
8413 * 2. the {"*"} for elements in no namespace.
8414 */
8415 ctxt->state =
8416 xmlAutomataNewTransition2(ctxt->am,
8417 start, NULL, BAD_CAST "*", NULL, type);
8418 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8419
8420 } else if (wild->nsSet != NULL) {
8421 ns = wild->nsSet;
8422 do {
8423 ctxt->state = start;
8424 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8425 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8426 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8427 ns = ns->next;
8428 } while (ns != NULL);
8429
8430 } else if (wild->negNsSet != NULL) {
8431 xmlAutomataStatePtr deadEnd;
8432
8433 deadEnd = xmlAutomataNewState(ctxt->am);
8434 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8435 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8436 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8437 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8438 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8439 }
8440 } else {
8441 int counter;
8442 xmlAutomataStatePtr hop;
8443 int maxOccurs =
8444 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8445 int minOccurs =
8446 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8447
8448 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8449 hop = xmlAutomataNewState(ctxt->am);
8450 if (wild->any == 1) {
8451 ctxt->state =
8452 xmlAutomataNewTransition2(ctxt->am,
8453 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8454 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8455 ctxt->state =
8456 xmlAutomataNewTransition2(ctxt->am,
8457 start, NULL, BAD_CAST "*", NULL, type);
8458 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8459 } else if (wild->nsSet != NULL) {
8460 ns = wild->nsSet;
8461 do {
8462 ctxt->state =
8463 xmlAutomataNewTransition2(ctxt->am,
8464 start, NULL, BAD_CAST "*", ns->value, type);
8465 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8466 ns = ns->next;
8467 } while (ns != NULL);
8468
8469 } else if (wild->negNsSet != NULL) {
8470 xmlAutomataStatePtr deadEnd;
8471
8472 deadEnd = xmlAutomataNewState(ctxt->am);
8473 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8474 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8475 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8476 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8477 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8478 }
8479 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8480 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8481 }
8482 if (type->minOccurs == 0) {
8483 xmlAutomataNewEpsilon(ctxt->am, start, end);
8484 }
8485 ctxt->state = end;
8486 break;
8487 }
8488 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008489 xmlAutomataStatePtr oldstate;
8490 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008491
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008492 /*
8493 * IMPORTANT: This puts element declarations
8494 * (and never element decl. references) into the
8495 * automaton. This is crucial and should not be changed,
8496 * since validating functions rely now on it.
8497 */
8498 particle = (xmlSchemaElementPtr) type;
8499 if (particle->ref != NULL) {
8500 if (particle->refDecl == NULL) {
8501 /*
8502 * Skip content model creation if the reference
8503 * did not resolve to a declaration.
8504 */
8505 break;
8506 } else {
8507 /*
8508 * Referenced global element declaration.
8509 */
8510 elemDecl = particle->refDecl;
8511 }
8512 } else {
8513 /*
8514 * Anonymous element declaration.
8515 */
8516 elemDecl = particle;
8517 }
8518
8519 oldstate = ctxt->state;
8520
8521 if (particle->maxOccurs >= UNBOUNDED) {
8522 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008523 xmlAutomataStatePtr tmp;
8524 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008525
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008526 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008527 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008528 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008529 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008530 particle->minOccurs - 1, UNBOUNDED);
8531 ctxt->state =
8532 xmlAutomataNewTransition2(ctxt->am,
8533 ctxt->state, NULL,
8534 elemDecl->name,
8535 elemDecl->targetNamespace,
8536 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008537 tmp = ctxt->state;
8538 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008539 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008540 ctxt->state =
8541 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008542 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008543
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008544 } else {
8545 ctxt->state =
8546 xmlAutomataNewTransition2(ctxt->am,
8547 ctxt->state, NULL,
8548 elemDecl->name,
8549 elemDecl->targetNamespace,
8550 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008551 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8552 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008553 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008554 /* basically an elem* */
8555 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8556 ctxt->state);
8557 }
8558 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008559 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008560 xmlAutomataStatePtr tmp;
8561 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008562
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008563 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8564 oldstate, NULL);
8565 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008566 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008567 particle->minOccurs - 1,
8568 particle->maxOccurs - 1);
8569 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8570 ctxt->state,
8571 NULL,
8572 elemDecl->name,
8573 elemDecl->targetNamespace,
8574 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008575 tmp = ctxt->state;
8576 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008577 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008578 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008579 NULL, counter);
8580 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008581 /* basically an elem? */
8582 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008583 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008584 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008585
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008586 } else {
8587 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8588 ctxt->state,
8589 NULL,
8590 elemDecl->name,
8591 elemDecl->targetNamespace,
8592 (xmlSchemaTypePtr) elemDecl);
8593 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008594 /* basically an elem? */
8595 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008596 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008597 }
8598 }
8599 break;
8600 }
8601 case XML_SCHEMA_TYPE_SEQUENCE:{
8602 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008603
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008604 /*
8605 * If max and min occurances are default (1) then
8606 * simply iterate over the subtypes
8607 */
8608 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8609 subtypes = type->subtypes;
8610 while (subtypes != NULL) {
8611 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8612 subtypes = subtypes->next;
8613 }
8614 } else {
8615 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008616
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008617 if (type->maxOccurs >= UNBOUNDED) {
8618 if (type->minOccurs > 1) {
8619 xmlAutomataStatePtr tmp;
8620 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008621
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008622 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8623 oldstate,
8624 NULL);
8625 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008626
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008627 counter = xmlAutomataNewCounter(ctxt->am,
8628 type->
8629 minOccurs - 1,
8630 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008631
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008632 subtypes = type->subtypes;
8633 while (subtypes != NULL) {
8634 xmlSchemaBuildAContentModel(subtypes, ctxt,
8635 name);
8636 subtypes = subtypes->next;
8637 }
8638 tmp = ctxt->state;
8639 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8640 oldstate, counter);
8641 ctxt->state =
8642 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8643 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008644
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008645 } else {
8646 subtypes = type->subtypes;
8647 while (subtypes != NULL) {
8648 xmlSchemaBuildAContentModel(subtypes, ctxt,
8649 name);
8650 subtypes = subtypes->next;
8651 }
8652 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8653 oldstate);
8654 if (type->minOccurs == 0) {
8655 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8656 ctxt->state);
8657 }
8658 }
8659 } else if ((type->maxOccurs > 1)
8660 || (type->minOccurs > 1)) {
8661 xmlAutomataStatePtr tmp;
8662 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008663
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008664 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8665 oldstate,
8666 NULL);
8667 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008668
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008669 counter = xmlAutomataNewCounter(ctxt->am,
8670 type->minOccurs -
8671 1,
8672 type->maxOccurs -
8673 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008674
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008675 subtypes = type->subtypes;
8676 while (subtypes != NULL) {
8677 xmlSchemaBuildAContentModel(subtypes, ctxt,
8678 name);
8679 subtypes = subtypes->next;
8680 }
8681 tmp = ctxt->state;
8682 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8683 counter);
8684 ctxt->state =
8685 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8686 counter);
8687 if (type->minOccurs == 0) {
8688 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8689 ctxt->state);
8690 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008691
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008692 } else {
8693 subtypes = type->subtypes;
8694 while (subtypes != NULL) {
8695 xmlSchemaBuildAContentModel(subtypes, ctxt,
8696 name);
8697 subtypes = subtypes->next;
8698 }
8699 if (type->minOccurs == 0) {
8700 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8701 ctxt->state);
8702 }
8703 }
8704 }
8705 break;
8706 }
8707 case XML_SCHEMA_TYPE_CHOICE:{
8708 xmlSchemaTypePtr subtypes;
8709 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008710
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008711 start = ctxt->state;
8712 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008713
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008714 /*
8715 * iterate over the subtypes and remerge the end with an
8716 * epsilon transition
8717 */
8718 if (type->maxOccurs == 1) {
8719 subtypes = type->subtypes;
8720 while (subtypes != NULL) {
8721 ctxt->state = start;
8722 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8723 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8724 subtypes = subtypes->next;
8725 }
8726 } else {
8727 int counter;
8728 xmlAutomataStatePtr hop;
8729 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8730 UNBOUNDED : type->maxOccurs - 1;
8731 int minOccurs =
8732 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008733
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008734 /*
8735 * use a counter to keep track of the number of transtions
8736 * which went through the choice.
8737 */
8738 counter =
8739 xmlAutomataNewCounter(ctxt->am, minOccurs,
8740 maxOccurs);
8741 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008742
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008743 subtypes = type->subtypes;
8744 while (subtypes != NULL) {
8745 ctxt->state = start;
8746 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8747 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8748 subtypes = subtypes->next;
8749 }
8750 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8751 counter);
8752 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8753 counter);
8754 }
8755 if (type->minOccurs == 0) {
8756 xmlAutomataNewEpsilon(ctxt->am, start, end);
8757 }
8758 ctxt->state = end;
8759 break;
8760 }
8761 case XML_SCHEMA_TYPE_ALL:{
8762 xmlAutomataStatePtr start;
8763 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008764
Daniel Veillard3646d642004-06-02 19:19:14 +00008765 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008766 int lax;
8767
8768 subtypes = type->subtypes;
8769 if (subtypes == NULL)
8770 break;
8771 start = ctxt->state;
8772 while (subtypes != NULL) {
8773 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008774 /*
8775 * the following 'if' was needed to fix bug 139897
8776 * not quite sure why it only needs to be done for
8777 * elements with a 'ref', but it seems to work ok.
8778 */
8779 if (subtypes->ref != NULL)
8780 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008781 elem = (xmlSchemaElementPtr) subtypes;
8782 /*
8783 * NOTE: The {max occurs} of all the particles in the
8784 * {particles} of the group must be 0 or 1.
8785 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008786 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008787 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8788 ctxt->state,
8789 elem->name,
8790 elem->targetNamespace,
8791 1, 1, subtypes);
8792 } else if ((elem->minOccurs == 0) &&
8793 (elem->maxOccurs == 1)) {
8794
8795 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8796 ctxt->state,
8797 elem->name,
8798 elem->targetNamespace,
8799 0,
8800 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008801 subtypes);
8802 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008803 /*
8804 * NOTE: if maxOccurs == 0 then no transition will be
8805 * created.
8806 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008807 subtypes = subtypes->next;
8808 }
8809 lax = type->minOccurs == 0;
8810 ctxt->state =
8811 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8812 lax);
8813 break;
8814 }
8815 case XML_SCHEMA_TYPE_RESTRICTION:
8816 if (type->subtypes != NULL)
8817 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8818 break;
8819 case XML_SCHEMA_TYPE_EXTENSION:
8820 if (type->baseType != NULL) {
8821 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008822
8823 /*
8824 * TODO: Circular definitions will be checked at the
8825 * constraint level. So remove this when the complex type
8826 * constraints are implemented.
8827 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008828 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008829 /* TODO: Change the error code. */
8830 xmlSchemaPCustomErr(ctxt,
8831 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8832 NULL, type, type->node,
8833 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008834 return;
8835 }
8836 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008837 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008838 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008839 subtypes = type->subtypes;
8840 while (subtypes != NULL) {
8841 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8842 subtypes = subtypes->next;
8843 }
8844 } else if (type->subtypes != NULL)
8845 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8846 break;
8847 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008848 /*
8849 * Handle model group definition references.
8850 * NOTE: type->subtypes is the referenced model grop definition;
8851 * and type->subtypes->subtypes is the model group (i.e. <all> or
8852 * <choice> or <sequence>).
8853 */
8854 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8855 (type->subtypes->subtypes != NULL)) {
8856 xmlSchemaTypePtr modelGr;
8857 xmlAutomataStatePtr start, end;
8858
8859 modelGr = type->subtypes->subtypes;
8860 start = ctxt->state;
8861 end = xmlAutomataNewState(ctxt->am);
8862 if (type->maxOccurs == 1) {
8863 ctxt->state = start;
8864 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8865 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8866 } else {
8867 int counter;
8868 xmlAutomataStatePtr hop;
8869 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8870 UNBOUNDED : type->maxOccurs - 1;
8871 int minOccurs =
8872 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8873
8874 counter =
8875 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8876 hop = xmlAutomataNewState(ctxt->am);
8877 ctxt->state = start;
8878 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8879 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8880 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8881 counter);
8882 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8883 counter);
8884 }
8885 if (type->minOccurs == 0) {
8886 xmlAutomataNewEpsilon(ctxt->am, start, end);
8887 }
8888 ctxt->state = end;
8889 break;
8890 }
8891 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008892 case XML_SCHEMA_TYPE_COMPLEX:
8893 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8894 if (type->subtypes != NULL)
8895 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8896 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008897 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8898 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008899 default:
8900 xmlGenericError(xmlGenericErrorContext,
8901 "Found unexpected type %d in %s content model\n",
8902 type->type, name);
8903 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008904 }
8905}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008906
Daniel Veillard4255d502002-04-16 15:50:10 +00008907/**
8908 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008909 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00008910 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008911 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008912 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008913 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00008914 */
8915static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008916xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008917 xmlSchemaParserCtxtPtr ctxt,
8918 const xmlChar * name)
8919{
Daniel Veillard4255d502002-04-16 15:50:10 +00008920 xmlAutomataStatePtr start;
8921
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008922 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
8923 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8924 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
8925 (type->contModel != NULL))
8926 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008927
8928#ifdef DEBUG_CONTENT
8929 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008930 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008931#endif
8932
Daniel Veillard4255d502002-04-16 15:50:10 +00008933 ctxt->am = xmlNewAutomata();
8934 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008935 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008936 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008937 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008938 }
8939 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008940 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008941 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008942 type->contModel = xmlAutomataCompile(ctxt->am);
8943 if (type->contModel == NULL) {
8944 xmlSchemaPCustomErr(ctxt,
8945 XML_SCHEMAP_INTERNAL,
8946 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008947 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008948 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008949 xmlSchemaPCustomErr(ctxt,
8950 XML_SCHEMAP_NOT_DETERMINISTIC,
8951 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008952 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008953 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008954 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008955#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008956 xmlGenericError(xmlGenericErrorContext,
8957 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008959#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008960 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008961 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008962 xmlFreeAutomata(ctxt->am);
8963 ctxt->am = NULL;
8964}
8965
8966/**
8967 * xmlSchemaRefFixupCallback:
8968 * @elem: the schema element context
8969 * @ctxt: the schema parser context
8970 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008971 * Resolves the references of an element declaration
8972 * or particle, which has an element declaration as it's
8973 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008974 */
8975static void
8976xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008977 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008978 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008979 const xmlChar * context ATTRIBUTE_UNUSED,
8980 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008981{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008982 if ((ctxt == NULL) || (elem == NULL) ||
8983 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008984 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008985 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008986 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008987 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008988
Daniel Veillardc0826a72004-08-10 14:17:33 +00008989 /*
8990 * TODO: Evaluate, what errors could occur if the declaration is not
8991 * found. It might be possible that the "typefixup" might crash if
8992 * no ref declaration was found.
8993 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008994 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008995 if (elemDecl == NULL) {
8996 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008997 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008998 NULL, (xmlSchemaTypePtr) elem, elem->node,
8999 "ref", elem->ref, elem->refNs,
9000 XML_SCHEMA_TYPE_ELEMENT, NULL);
9001 } else
9002 elem->refDecl = elemDecl;
9003 } else {
9004 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9005 xmlSchemaTypePtr type;
9006
9007 /* (type definition) ... otherwise the type definition ·resolved·
9008 * to by the ·actual value· of the type [attribute] ...
9009 */
9010 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9011 elem->namedTypeNs);
9012 if (type == NULL) {
9013 xmlSchemaPResCompAttrErr(ctxt,
9014 XML_SCHEMAP_SRC_RESOLVE,
9015 NULL, (xmlSchemaTypePtr) elem, elem->node,
9016 "type", elem->namedType, elem->namedTypeNs,
9017 XML_SCHEMA_TYPE_BASIC, "type definition");
9018 } else
9019 elem->subtypes = type;
9020 }
9021 if (elem->substGroup != NULL) {
9022 xmlSchemaElementPtr substHead;
9023
9024 /*
9025 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9026 * substitutionGroup?
9027 */
9028 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009029 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009030 if (substHead == NULL) {
9031 xmlSchemaPResCompAttrErr(ctxt,
9032 XML_SCHEMAP_SRC_RESOLVE,
9033 NULL, (xmlSchemaTypePtr) elem, NULL,
9034 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9035 XML_SCHEMA_TYPE_ELEMENT, NULL);
9036 } else {
9037 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9038 /*
9039 * (type definition)...otherwise the {type definition} of the
9040 * element declaration ·resolved· to by the ·actual value· of
9041 * the substitutionGroup [attribute], if present
9042 */
9043 if (elem->subtypes == NULL)
9044 elem->subtypes = substHead->subtypes;
9045 }
9046 }
9047 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9048 (elem->substGroup == NULL))
9049 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9050 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009051}
9052
William M. Bracke7091952004-05-11 15:09:58 +00009053/**
9054 * xmlSchemaParseListRefFixup:
9055 * @type: the schema type definition
9056 * @ctxt: the schema parser context
9057 *
9058 * Fixup of the itemType reference of the list type.
9059 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009060static void
William M. Bracke7091952004-05-11 15:09:58 +00009061xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009062{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009063
Daniel Veillard01fa6152004-06-29 17:04:39 +00009064 if (((type->base == NULL) &&
9065 (type->subtypes == NULL)) ||
9066 ((type->base != NULL) &&
9067 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009068 /*
9069 * src-list-itemType-or-simpleType
9070 * Either the itemType [attribute] or the <simpleType> [child] of
9071 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009072 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009073 /*
9074 * TODO: Move this to the parse function.
9075 */
9076 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009077 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009078 NULL, type, type->node,
9079 "The attribute 'itemType' and the <simpleType> child "
9080 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009081 } else if (type->base!= NULL) {
9082 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9083 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009084 xmlSchemaPResCompAttrErr(ctxt,
9085 XML_SCHEMAP_SRC_RESOLVE,
9086 NULL, type, type->node,
9087 "itemType", type->base, type->baseNs,
9088 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009089 }
9090 }
9091 if ((type->subtypes != NULL) &&
9092 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9093 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009094}
9095
9096/**
9097 * xmlSchemaParseUnionRefCheck:
9098 * @typeDecl: the schema type definition
9099 * @ctxt: the schema parser context
9100 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009101 * Checks and builds the memberTypes of the union type.
9102 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009103 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009104static int
William M. Bracke7091952004-05-11 15:09:58 +00009105xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009106 xmlSchemaParserCtxtPtr ctxt)
9107{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009108
Daniel Veillard01fa6152004-06-29 17:04:39 +00009109 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9110 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009111
Daniel Veillard01fa6152004-06-29 17:04:39 +00009112 /* 1 If the <union> alternative is chosen, then [Definition:]
9113 * define the explicit members as the type definitions ·resolved·
9114 * to by the items in the ·actual value· of the memberTypes [attribute],
9115 * if any, followed by the type definitions corresponding to the
9116 * <simpleType>s among the [children] of <union>, if any.
9117 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009118
Daniel Veillard01fa6152004-06-29 17:04:39 +00009119 if (type->type != XML_SCHEMA_TYPE_UNION)
9120 return (-1);
9121 if (ctxt->ctxtType == NULL) {
9122 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009123 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009124 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9125 "available", NULL, NULL);
9126 return (-1);
9127 }
9128 /*
9129 * src-union-memberTypes-or-simpleTypes
9130 * Either the memberTypes [attribute] of the <union> element must
9131 * be non-empty or there must be at least one simpleType [child].
9132 */
9133 if ((type->base == NULL) &&
9134 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009135 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009136 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009137 NULL, NULL, type->node,
9138 "Either the attribute 'memberTypes' must be non-empty "
9139 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009140 }
9141
9142 ctxtType = ctxt->ctxtType;
9143 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009144 xmlAttrPtr attr;
9145 const xmlChar *cur, *end;
9146 xmlChar *tmp;
9147 const xmlChar *localName, *uri;
9148
9149 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009150 cur = type->base;
9151 do {
9152 while (IS_BLANK_CH(*cur))
9153 cur++;
9154 end = cur;
9155 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9156 end++;
9157 if (end == cur)
9158 break;
9159 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009160 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9161 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9162 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009163 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009164 xmlSchemaPResCompAttrErr(ctxt,
9165 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9166 NULL, NULL, type->node, "memberTypes", localName, uri,
9167 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009168 } else {
9169 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9170 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9171 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9172 if (link == NULL) {
9173 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9174 return (-1);
9175 }
9176 link->type = memberType;
9177 link->next = NULL;
9178 if (lastLink == NULL)
9179 ctxtType->memberTypes = link;
9180 else
9181 lastLink->next = link;
9182 lastLink = link;
9183 }
9184 xmlFree(tmp);
9185 cur = end;
9186 } while (*cur != 0);
9187 }
9188 /*
9189 * Add local simple types,
9190 */
9191 memberType = type->subtypes;
9192 while (memberType != NULL) {
9193 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9194 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9195 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9196 if (link == NULL) {
9197 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9198 return (-1);
9199 }
9200 link->type = memberType;
9201 link->next = NULL;
9202 if (lastLink == NULL)
9203 ctxtType->memberTypes = link;
9204 else
9205 lastLink->next = link;
9206 lastLink = link;
9207 memberType = memberType->next;
9208 }
9209 /*
9210 * The actual value is then formed by replacing any union type
9211 * definition in the ·explicit members· with the members of their
9212 * {member type definitions}, in order.
9213 */
9214 link = ctxtType->memberTypes;
9215 while (link != NULL) {
9216 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9217 subLink = link->type->memberTypes;
9218 if (subLink != NULL) {
9219 link->type = subLink->type;
9220 if (subLink->next != NULL) {
9221 lastLink = link->next;
9222 subLink = subLink->next;
9223 prevLink = link;
9224 while (subLink != NULL) {
9225 newLink = (xmlSchemaTypeLinkPtr)
9226 xmlMalloc(sizeof(xmlSchemaTypeLink));
9227 if (newLink == NULL) {
9228 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9229 NULL);
9230 return (-1);
9231 }
9232 newLink->type = memberType;
9233 prevLink->next = newLink;
9234 prevLink = newLink;
9235 newLink->next = lastLink;
9236
9237 subLink = subLink->next;
9238 }
9239 }
9240 }
9241 }
9242 link = link->next;
9243 }
9244
9245 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009246}
9247
Daniel Veillard4255d502002-04-16 15:50:10 +00009248/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009249 * xmlSchemaIsDerivedFromBuiltInType:
9250 * @ctxt: the schema parser context
9251 * @type: the type definition
9252 * @valType: the value type
9253 *
9254 *
9255 * Returns 1 if the type has the given value type, or
9256 * is derived from such a type.
9257 */
William M. Brack803812b2004-06-03 02:11:24 +00009258static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009259xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9260 xmlSchemaTypePtr type, int valType)
9261{
9262 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009263 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009264 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009265 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009266 return(1);
9267 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9268 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9269 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9270 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9271 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9272 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9273 if (type->baseType != NULL)
9274 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9275 valType));
9276 } else if ((type->subtypes != NULL) &&
9277 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9278 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9279 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9280 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9281 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9282 valType));
9283 }
9284
9285 return (0);
9286}
9287
9288/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009289 * xmlSchemaIsDerivedFromBuiltInType:
9290 * @type: the simpleType definition
9291 *
9292 * Returns the primitive type of the given type or
9293 * NULL in case of error.
9294 */
9295static xmlSchemaTypePtr
9296xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9297{
9298 while (type != NULL) {
9299 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9300 return (type);
9301 type = type->baseType;
9302 }
9303
9304 return (NULL);
9305}
9306
9307
9308/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009309 * xmlSchemaBuildAttributeUsesOwned:
9310 * @ctxt: the schema parser context
9311 * @type: the complex type definition
9312 * @cur: the attribute declaration list
9313 * @lastUse: the top of the attribute use list
9314 *
9315 * Builds the attribute uses list on the given complex type.
9316 * This one is supposed to be called by
9317 * xmlSchemaBuildAttributeValidation only.
9318 */
9319static int
9320xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9321 xmlSchemaAttributePtr cur,
9322 xmlSchemaAttributeLinkPtr *uses,
9323 xmlSchemaAttributeLinkPtr *lastUse)
9324{
9325 xmlSchemaAttributeLinkPtr tmp;
9326 while (cur != NULL) {
9327 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9328 /*
9329 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9330 * to by the ·actual value·s of the ref [attribute] of the
9331 * <attributeGroup> [children], if any."
9332 */
9333 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9334 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9335 lastUse) == -1) {
9336 return (-1);
9337 }
9338 } else {
9339 /* W3C: "1 The set of attribute uses corresponding to the
9340 * <attribute> [children], if any."
9341 */
9342 tmp = (xmlSchemaAttributeLinkPtr)
9343 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9344 if (tmp == NULL) {
9345 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9346 return (-1);
9347 }
9348 tmp->attr = cur;
9349 tmp->next = NULL;
9350 if (*uses == NULL)
9351 *uses = tmp;
9352 else
9353 (*lastUse)->next = tmp;
9354 *lastUse = tmp;
9355 }
9356 cur = cur->next;
9357 }
9358 return (0);
9359}
9360
Daniel Veillard50355f02004-06-08 17:52:16 +00009361/**
9362 * xmlSchemaCloneWildcardNsConstraints:
9363 * @ctxt: the schema parser context
9364 * @dest: the destination wildcard
9365 * @source: the source wildcard
9366 *
9367 * Clones the namespace constraints of source
9368 * and assignes them to dest.
9369 * Returns -1 on internal error, 0 otherwise.
9370 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009371static int
9372xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9373 xmlSchemaWildcardPtr *dest,
9374 xmlSchemaWildcardPtr source)
9375{
9376 xmlSchemaWildcardNsPtr cur, tmp, last;
9377
9378 if ((source == NULL) || (*dest == NULL))
9379 return(-1);
9380 (*dest)->any = source->any;
9381 cur = source->nsSet;
9382 last = NULL;
9383 while (cur != NULL) {
9384 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9385 if (tmp == NULL)
9386 return(-1);
9387 tmp->value = cur->value;
9388 if (last == NULL)
9389 (*dest)->nsSet = tmp;
9390 else
9391 last->next = tmp;
9392 last = tmp;
9393 cur = cur->next;
9394 }
9395 if ((*dest)->negNsSet != NULL)
9396 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9397 if (source->negNsSet != NULL) {
9398 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9399 if ((*dest)->negNsSet == NULL)
9400 return(-1);
9401 (*dest)->negNsSet->value = source->negNsSet->value;
9402 } else
9403 (*dest)->negNsSet = NULL;
9404 return(0);
9405}
9406
Daniel Veillard50355f02004-06-08 17:52:16 +00009407/**
9408 * xmlSchemaUnionWildcards:
9409 * @ctxt: the schema parser context
9410 * @completeWild: the first wildcard
9411 * @curWild: the second wildcard
9412 *
9413 * Unions the namespace constraints of the given wildcards.
9414 * @completeWild will hold the resulting union.
9415 * Returns a positive error code on failure, -1 in case of an
9416 * internal error, 0 otherwise.
9417 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009418static int
9419xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9420 xmlSchemaWildcardPtr completeWild,
9421 xmlSchemaWildcardPtr curWild)
9422{
9423 xmlSchemaWildcardNsPtr cur, curB, tmp;
9424
9425 /*
9426 * 1 If O1 and O2 are the same value, then that value must be the
9427 * value.
9428 */
9429 if ((completeWild->any == curWild->any) &&
9430 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9431 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9432
9433 if ((completeWild->negNsSet == NULL) ||
9434 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9435
9436 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009437 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009438
9439 /*
9440 * Check equality of sets.
9441 */
9442 cur = completeWild->nsSet;
9443 while (cur != NULL) {
9444 found = 0;
9445 curB = curWild->nsSet;
9446 while (curB != NULL) {
9447 if (cur->value == curB->value) {
9448 found = 1;
9449 break;
9450 }
9451 curB = curB->next;
9452 }
9453 if (!found)
9454 break;
9455 cur = cur->next;
9456 }
9457 if (found)
9458 return(0);
9459 } else
9460 return(0);
9461 }
9462 }
9463 /*
9464 * 2 If either O1 or O2 is any, then any must be the value
9465 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009466 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009467 if (completeWild->any == 0) {
9468 completeWild->any = 1;
9469 if (completeWild->nsSet != NULL) {
9470 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9471 completeWild->nsSet = NULL;
9472 }
9473 if (completeWild->negNsSet != NULL) {
9474 xmlFree(completeWild->negNsSet);
9475 completeWild->negNsSet = NULL;
9476 }
9477 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009478 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009479 }
9480 /*
9481 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9482 * then the union of those sets must be the value.
9483 */
9484 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9485 int found;
9486 xmlSchemaWildcardNsPtr start;
9487
9488 cur = curWild->nsSet;
9489 start = completeWild->nsSet;
9490 while (cur != NULL) {
9491 found = 0;
9492 curB = start;
9493 while (curB != NULL) {
9494 if (cur->value == curB->value) {
9495 found = 1;
9496 break;
9497 }
9498 curB = curB->next;
9499 }
9500 if (!found) {
9501 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9502 if (tmp == NULL)
9503 return (-1);
9504 tmp->value = cur->value;
9505 tmp->next = completeWild->nsSet;
9506 completeWild->nsSet = tmp;
9507 }
9508 cur = cur->next;
9509 }
9510
9511 return(0);
9512 }
9513 /*
9514 * 4 If the two are negations of different values (namespace names
9515 * or ·absent·), then a pair of not and ·absent· must be the value.
9516 */
9517 if ((completeWild->negNsSet != NULL) &&
9518 (curWild->negNsSet != NULL) &&
9519 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9520 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009521
9522 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009523 }
9524 /*
9525 * 5.
9526 */
9527 if (((completeWild->negNsSet != NULL) &&
9528 (completeWild->negNsSet->value != NULL) &&
9529 (curWild->nsSet != NULL)) ||
9530 ((curWild->negNsSet != NULL) &&
9531 (curWild->negNsSet->value != NULL) &&
9532 (completeWild->nsSet != NULL))) {
9533
9534 int nsFound, absentFound = 0;
9535
9536 if (completeWild->nsSet != NULL) {
9537 cur = completeWild->nsSet;
9538 curB = curWild->negNsSet;
9539 } else {
9540 cur = curWild->nsSet;
9541 curB = completeWild->negNsSet;
9542 }
9543 nsFound = 0;
9544 while (cur != NULL) {
9545 if (cur->value == NULL)
9546 absentFound = 1;
9547 else if (cur->value == curB->value)
9548 nsFound = 1;
9549 if (nsFound && absentFound)
9550 break;
9551 cur = cur->next;
9552 }
9553
9554 if (nsFound && absentFound) {
9555 /*
9556 * 5.1 If the set S includes both the negated namespace
9557 * name and ·absent·, then any must be the value.
9558 */
9559 completeWild->any = 1;
9560 if (completeWild->nsSet != NULL) {
9561 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9562 completeWild->nsSet = NULL;
9563 }
9564 if (completeWild->negNsSet != NULL) {
9565 xmlFree(completeWild->negNsSet);
9566 completeWild->negNsSet = NULL;
9567 }
9568 } else if (nsFound && (!absentFound)) {
9569 /*
9570 * 5.2 If the set S includes the negated namespace name
9571 * but not ·absent·, then a pair of not and ·absent· must
9572 * be the value.
9573 */
9574 if (completeWild->nsSet != NULL) {
9575 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9576 completeWild->nsSet = NULL;
9577 }
9578 if (completeWild->negNsSet == NULL) {
9579 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9580 if (completeWild->negNsSet == NULL)
9581 return (-1);
9582 }
9583 completeWild->negNsSet->value = NULL;
9584 } else if ((!nsFound) && absentFound) {
9585 /*
9586 * 5.3 If the set S includes ·absent· but not the negated
9587 * namespace name, then the union is not expressible.
9588 */
9589 xmlSchemaPErr(ctxt, completeWild->node,
9590 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009591 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009592 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009593 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009594 } else if ((!nsFound) && (!absentFound)) {
9595 /*
9596 * 5.4 If the set S does not include either the negated namespace
9597 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9598 * and a namespace name must be the value.
9599 */
9600 if (completeWild->negNsSet == NULL) {
9601 if (completeWild->nsSet != NULL) {
9602 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9603 completeWild->nsSet = NULL;
9604 }
9605 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9606 if (completeWild->negNsSet == NULL)
9607 return (-1);
9608 completeWild->negNsSet->value = curWild->negNsSet->value;
9609 }
9610 }
9611 return (0);
9612 }
9613 /*
9614 * 6.
9615 */
9616 if (((completeWild->negNsSet != NULL) &&
9617 (completeWild->negNsSet->value == NULL) &&
9618 (curWild->nsSet != NULL)) ||
9619 ((curWild->negNsSet != NULL) &&
9620 (curWild->negNsSet->value == NULL) &&
9621 (completeWild->nsSet != NULL))) {
9622
9623 if (completeWild->nsSet != NULL) {
9624 cur = completeWild->nsSet;
9625 } else {
9626 cur = curWild->nsSet;
9627 }
9628 while (cur != NULL) {
9629 if (cur->value == NULL) {
9630 /*
9631 * 6.1 If the set S includes ·absent·, then any must be the
9632 * value.
9633 */
9634 completeWild->any = 1;
9635 if (completeWild->nsSet != NULL) {
9636 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9637 completeWild->nsSet = NULL;
9638 }
9639 if (completeWild->negNsSet != NULL) {
9640 xmlFree(completeWild->negNsSet);
9641 completeWild->negNsSet = NULL;
9642 }
9643 return (0);
9644 }
9645 cur = cur->next;
9646 }
9647 if (completeWild->negNsSet == NULL) {
9648 /*
9649 * 6.2 If the set S does not include ·absent·, then a pair of not
9650 * and ·absent· must be the value.
9651 */
9652 if (completeWild->nsSet != NULL) {
9653 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9654 completeWild->nsSet = NULL;
9655 }
9656 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9657 if (completeWild->negNsSet == NULL)
9658 return (-1);
9659 completeWild->negNsSet->value = NULL;
9660 }
9661 return (0);
9662 }
9663 return (0);
9664
9665}
9666
Daniel Veillard50355f02004-06-08 17:52:16 +00009667/**
9668 * xmlSchemaIntersectWildcards:
9669 * @ctxt: the schema parser context
9670 * @completeWild: the first wildcard
9671 * @curWild: the second wildcard
9672 *
9673 * Intersects the namespace constraints of the given wildcards.
9674 * @completeWild will hold the resulting intersection.
9675 * Returns a positive error code on failure, -1 in case of an
9676 * internal error, 0 otherwise.
9677 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009678static int
9679xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9680 xmlSchemaWildcardPtr completeWild,
9681 xmlSchemaWildcardPtr curWild)
9682{
William M. Brack803812b2004-06-03 02:11:24 +00009683 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009684
9685 /*
9686 * 1 If O1 and O2 are the same value, then that value must be the
9687 * value.
9688 */
9689 if ((completeWild->any == curWild->any) &&
9690 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9691 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9692
9693 if ((completeWild->negNsSet == NULL) ||
9694 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9695
9696 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009697 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009698
9699 /*
9700 * Check equality of sets.
9701 */
9702 cur = completeWild->nsSet;
9703 while (cur != NULL) {
9704 found = 0;
9705 curB = curWild->nsSet;
9706 while (curB != NULL) {
9707 if (cur->value == curB->value) {
9708 found = 1;
9709 break;
9710 }
9711 curB = curB->next;
9712 }
9713 if (!found)
9714 break;
9715 cur = cur->next;
9716 }
9717 if (found)
9718 return(0);
9719 } else
9720 return(0);
9721 }
9722 }
9723 /*
9724 * 2 If either O1 or O2 is any, then the other must be the value.
9725 */
9726 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9727 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9728 return(-1);
9729 return(0);
9730 }
9731 /*
9732 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9733 * name or ·absent·) and the other is a set of (namespace names or
9734 * ·absent·), then that set, minus the negated value if it was in
9735 * the set, minus ·absent· if it was in the set, must be the value.
9736 */
9737 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9738 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9739 const xmlChar *neg;
9740
9741 if (completeWild->nsSet == NULL) {
9742 neg = completeWild->negNsSet->value;
9743 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9744 return(-1);
9745 } else
9746 neg = curWild->negNsSet->value;
9747 /*
9748 * Remove absent and negated.
9749 */
9750 prev = NULL;
9751 cur = completeWild->nsSet;
9752 while (cur != NULL) {
9753 if (cur->value == NULL) {
9754 if (prev == NULL)
9755 completeWild->nsSet = cur->next;
9756 else
9757 prev->next = cur->next;
9758 xmlFree(cur);
9759 break;
9760 }
9761 prev = cur;
9762 cur = cur->next;
9763 }
9764 if (neg != NULL) {
9765 prev = NULL;
9766 cur = completeWild->nsSet;
9767 while (cur != NULL) {
9768 if (cur->value == neg) {
9769 if (prev == NULL)
9770 completeWild->nsSet = cur->next;
9771 else
9772 prev->next = cur->next;
9773 xmlFree(cur);
9774 break;
9775 }
9776 prev = cur;
9777 cur = cur->next;
9778 }
9779 }
9780
9781 return(0);
9782 }
9783 /*
9784 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9785 * then the intersection of those sets must be the value.
9786 */
9787 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9788 int found;
9789
9790 cur = completeWild->nsSet;
9791 prev = NULL;
9792 while (cur != NULL) {
9793 found = 0;
9794 curB = curWild->nsSet;
9795 while (curB != NULL) {
9796 if (cur->value == curB->value) {
9797 found = 1;
9798 break;
9799 }
9800 curB = curB->next;
9801 }
9802 if (!found) {
9803 if (prev == NULL)
9804 completeWild->nsSet = cur->next;
9805 else
9806 prev->next = cur->next;
9807 tmp = cur->next;
9808 xmlFree(cur);
9809 cur = tmp;
9810 continue;
9811 }
9812 prev = cur;
9813 cur = cur->next;
9814 }
9815
9816 return(0);
9817 }
9818 /* 5 If the two are negations of different namespace names,
9819 * then the intersection is not expressible
9820 */
9821 if ((completeWild->negNsSet != NULL) &&
9822 (curWild->negNsSet != NULL) &&
9823 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9824 (completeWild->negNsSet->value != NULL) &&
9825 (curWild->negNsSet->value != NULL)) {
9826
9827 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009828 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009829 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009830 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009831 }
9832 /*
9833 * 6 If the one is a negation of a namespace name and the other
9834 * is a negation of ·absent·, then the one which is the negation
9835 * of a namespace name must be the value.
9836 */
9837 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9838 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9839 (completeWild->negNsSet->value == NULL)) {
9840 completeWild->negNsSet->value = curWild->negNsSet->value;
9841 }
9842 return(0);
9843}
9844
Daniel Veillard50355f02004-06-08 17:52:16 +00009845/**
9846 * xmlSchemaIsWildcardNsConstraintSubset:
9847 * @ctxt: the schema parser context
9848 * @wildA: the first wildcard
9849 * @wildB: the second wildcard
9850 *
9851 * Returns 1 if the namespace constraint of @wildA is an intensional
9852 * subset of @wildB, 0 otherwise.
9853 */
9854static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009855xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9856 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009857{
Daniel Veillard3646d642004-06-02 19:19:14 +00009858
Daniel Veillard50355f02004-06-08 17:52:16 +00009859 /*
9860 * Schema Component Constraint: Wildcard Subset
9861 */
9862 /*
9863 * 1 super must be any.
9864 */
9865 if (wildB->any)
9866 return (1);
9867 /*
9868 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9869 * 2.2 super must be a pair of not and the same value.
9870 */
9871 if ((wildA->negNsSet != NULL) &&
9872 (wildB->negNsSet != NULL) &&
9873 (wildA->negNsSet->value == wildA->negNsSet->value))
9874 return (1);
9875 /*
9876 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9877 */
9878 if (wildA->nsSet != NULL) {
9879 /*
9880 * 3.2.1 super must be the same set or a superset thereof.
9881 */
9882 if (wildB->nsSet != NULL) {
9883 xmlSchemaWildcardNsPtr cur, curB;
9884 int found = 0;
9885
9886 cur = wildA->nsSet;
9887 while (cur != NULL) {
9888 found = 0;
9889 curB = wildB->nsSet;
9890 while (curB != NULL) {
9891 if (cur->value == curB->value) {
9892 found = 1;
9893 break;
9894 }
9895 curB = curB->next;
9896 }
9897 if (!found)
9898 return (0);
9899 cur = cur->next;
9900 }
9901 if (found)
9902 return (1);
9903 } else if (wildB->negNsSet != NULL) {
9904 xmlSchemaWildcardNsPtr cur;
9905 /*
9906 * 3.2.2 super must be a pair of not and a namespace name or
9907 * ·absent· and that value must not be in sub's set.
9908 */
9909 cur = wildA->nsSet;
9910 while (cur != NULL) {
9911 if (cur->value == wildB->negNsSet->value)
9912 return (0);
9913 cur = cur->next;
9914 }
9915 return (1);
9916 }
9917 }
9918 return (0);
9919}
9920
9921/**
9922 * xmlSchemaBuildCompleteAttributeWildcard:
9923 * @ctxt: the schema parser context
9924 * @attrs: the attribute list
9925 * @completeWild: the resulting complete wildcard
9926 *
9927 * Returns -1 in case of an internal error, 0 otherwise.
9928 */
9929static int
9930xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9931 xmlSchemaAttributePtr attrs,
9932 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009933{
9934 while (attrs != NULL) {
9935 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9936 xmlSchemaAttributeGroupPtr group;
9937
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009938 group = (xmlSchemaAttributeGroupPtr) attrs;
9939 /*
9940 * Handle attribute group references.
9941 */
9942 if (group->ref != NULL) {
9943 if (group->refItem == NULL) {
9944 /*
9945 * TODO: Should we raise a warning here?
9946 */
9947 /*
9948 * The referenced attribute group definition could not
9949 * be resolved beforehand, so skip.
9950 */
9951 attrs = attrs->next;
9952 continue;
9953 } else
9954 group = group->refItem;
9955 }
9956 /*
9957 * For every attribute group definition, an intersected wildcard
9958 * will be created (assumed that a wildcard exists on the
9959 * particular attr. gr. def. or on any contained attr. gr. def
9960 * at all).
9961 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
9962 * that the intersection will be performed only once.
9963 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009964 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9965 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009966 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9967 group->attributes, &group->attributeWildcard) == -1)
9968 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009969 }
9970 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9971 }
9972 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009973 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009974 /*
9975 * Copy the first encountered wildcard as context, except for the annotation.
9976 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009977 *completeWild = xmlSchemaAddWildcard(ctxt);
9978 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9979 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9980 completeWild, group->attributeWildcard) == -1)
9981 return (-1);
9982 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009983 /*
9984 * Although the complete wildcard might not correspond to any
9985 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009986 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +00009987 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009988 (*completeWild)->node = group->attributeWildcard->node;
9989
9990 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9991 xmlSchemaFreeWildcard(*completeWild);
9992 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009993 }
9994 }
9995 }
9996 attrs = attrs->next;
9997 }
9998
Daniel Veillard50355f02004-06-08 17:52:16 +00009999 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010000}
10001
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010002static int
10003xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10004 int *fixed,
10005 const xmlChar **value,
10006 xmlSchemaValPtr *val)
10007{
10008 *fixed = 0;
10009 *value = NULL;
10010 if (val != 0)
10011 *val = NULL;
10012
10013 if (item->defValue == NULL)
10014 item = item->refDecl;
10015
10016 if (item == NULL)
10017 return (0);
10018
10019 if (item->defValue != NULL) {
10020 *value = item->defValue;
10021 if (val != 0)
10022 *val = item->defVal;
10023 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10024 *fixed = 1;
10025 return (1);
10026 }
10027 return (0);
10028}
Daniel Veillard3646d642004-06-02 19:19:14 +000010029/**
10030 * xmlSchemaMatchesWildcardNs:
10031 * @wild: the wildcard
10032 * @ns: the namespace
10033 *
10034 *
10035 * Returns 1 if the given namespace matches the wildcard,
10036 * 0 otherwise.
10037 */
10038static int
10039xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10040{
10041 if (wild == NULL)
10042 return(0);
10043
10044 if (wild->any)
10045 return(1);
10046 else if (wild->nsSet != NULL) {
10047 xmlSchemaWildcardNsPtr cur;
10048
10049 cur = wild->nsSet;
10050 while (cur != NULL) {
10051 if (xmlStrEqual(cur->value, ns))
10052 return(1);
10053 cur = cur->next;
10054 }
10055 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10056 (!xmlStrEqual(wild->negNsSet->value, ns)))
10057 return(1);
10058
10059 return(0);
10060}
10061
10062/**
10063 * xmlSchemaBuildAttributeValidation:
10064 * @ctxt: the schema parser context
10065 * @type: the complex type definition
10066 *
10067 *
10068 * Builds the wildcard and the attribute uses on the given complex type.
10069 * Returns -1 if an internal error occurs, 0 otherwise.
10070 */
10071static int
10072xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10073{
10074 xmlSchemaTypePtr baseType = NULL;
10075 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010076 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010077 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010078 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010079 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010080 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010081 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010082
Daniel Veillard01fa6152004-06-29 17:04:39 +000010083 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010084 /*
10085 * Complex Type Definition with complex content Schema Component.
10086 *
10087 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010088 * TODO: Add checks for absent referenced attribute declarations and
10089 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010090 */
10091 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010092 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010093 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010094 "attribute uses already builded.\n",
10095 NULL, NULL);
10096 return (-1);
10097 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010098 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010099 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010100 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010101 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010102 type->name, NULL);
10103 return (-1);
10104 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010105 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010106 if (baseType == anyType)
10107 baseIsAnyType = 1;
10108 /*
10109 * Inherit the attribute uses of the base type.
10110 */
10111 /*
10112 * NOTE: It is allowed to "extend" the anyType complex type.
10113 */
10114 if (!baseIsAnyType) {
10115 if (baseType != NULL) {
10116 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10117 tmp = (xmlSchemaAttributeLinkPtr)
10118 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10119 if (tmp == NULL) {
10120 xmlSchemaPErrMemory(ctxt,
10121 "building attribute uses of complexType", NULL);
10122 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010123 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010124 tmp->attr = cur->attr;
10125 tmp->next = NULL;
10126 if (type->attributeUses == NULL) {
10127 type->attributeUses = tmp;
10128 } else
10129 lastBaseUse->next = tmp;
10130 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010131 }
10132 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010133 }
10134 if ((type->subtypes != NULL) &&
10135 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10136 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010137 /*
10138 * type --> (<simpleContent>|<complexContent>)
10139 * --> (<restriction>|<extension>) --> attributes
10140 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010141 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010142 } else {
10143 /* Short hand form of the complexType. */
10144 attrs = type->attributes;
10145 }
10146 /*
10147 * Handle attribute wildcards.
10148 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010149 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10150 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010151 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010152 * NOTE: During the parse time, the wildcard is created on the complexType
10153 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010154 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010155 if (err == -1) {
10156 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10157 "Internal error: xmlSchemaBuildAttributeValidation: "
10158 "failed to build an intersected attribute wildcard.\n",
10159 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010160 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010161 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010162
10163 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10164 ((baseIsAnyType) ||
10165 ((baseType != NULL) &&
10166 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10167 (baseType->attributeWildcard != NULL)))) {
10168 if (type->attributeWildcard != NULL) {
10169 /*
10170 * Union the complete wildcard with the base wildcard.
10171 */
10172 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10173 baseType->attributeWildcard) == -1)
10174 return (-1);
10175 } else {
10176 /*
10177 * Just inherit the wildcard.
10178 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010179 /*
10180 * NOTE: This is the only case where an attribute
10181 * wildcard is shared.
10182 */
10183 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10184 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010185 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010186 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010187 }
10188
10189 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10190 if (type->attributeWildcard != NULL) {
10191 /*
10192 * Derivation Valid (Restriction, Complex)
10193 * 4.1 The {base type definition} must also have one.
10194 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010195 if (baseType->attributeWildcard == NULL) {
10196 xmlSchemaPCustomErr(ctxt,
10197 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10198 NULL, type, NULL,
10199 "The type has an attribute wildcard, "
10200 "but the base type %s does not have one",
10201 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10202 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010203 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010204 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010205 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10206 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010207 xmlSchemaPCustomErr(ctxt,
10208 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10209 NULL, type, NULL,
10210 "The attribute wildcard is not a valid "
10211 "subset of the wildcard in the base type %s",
10212 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10213 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010214 return (1);
10215 }
10216 /* 4.3 Unless the {base type definition} is the ·ur-type
10217 * definition·, the complex type definition's {attribute
10218 * wildcard}'s {process contents} must be identical to or
10219 * stronger than the {base type definition}'s {attribute
10220 * wildcard}'s {process contents}, where strict is stronger
10221 * than lax is stronger than skip.
10222 */
10223 if ((type->baseType != anyType) &&
10224 (type->attributeWildcard->processContents <
10225 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010226 xmlSchemaPCustomErr(ctxt,
10227 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10228 NULL, type, NULL,
10229 "The 'process contents' of the attribute wildcard is weaker than "
10230 "the one in the base type %s",
10231 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10232 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010233 return (1);
10234 }
10235 }
10236 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10237 /*
10238 * Derivation Valid (Extension)
10239 * At this point the type and the base have both, either
10240 * no wildcard or a wildcard.
10241 */
10242 if ((baseType->attributeWildcard != NULL) &&
10243 (baseType->attributeWildcard != type->attributeWildcard)) {
10244 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010245 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010246 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010247 xmlSchemaPCustomErr(ctxt,
10248 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10249 NULL, type, NULL,
10250 "The attribute wildcard is not a valid "
10251 "superset of the one in the base type %s",
10252 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10253 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010254 return (1);
10255 }
10256 }
10257 }
10258
Daniel Veillard3646d642004-06-02 19:19:14 +000010259 /*
10260 * Gather attribute uses defined by this type.
10261 */
10262 if (attrs != NULL) {
10263 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10264 &uses, &lastUse) == -1) {
10265 return (-1);
10266 }
10267 }
10268 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10269 * "Two distinct attribute declarations in the {attribute uses} must
10270 * not have identical {name}s and {target namespace}s."
10271 *
10272 * For "extension" this is done further down.
10273 */
10274 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10275 cur = uses;
10276 while (cur != NULL) {
10277 tmp = cur->next;
10278 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010279 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10280 xmlSchemaGetAttrName(tmp->attr))) &&
10281 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10282 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10283
10284 xmlSchemaPAttrUseErr(ctxt,
10285 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10286 NULL, type, NULL, cur->attr,
10287 "Duplicate attribute use %s specified",
10288 xmlSchemaFormatNsUriLocal(&str,
10289 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10290 xmlSchemaGetAttrName(tmp->attr))
10291 );
10292 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010293 break;
10294 }
10295 tmp = tmp->next;
10296 }
10297 cur = cur->next;
10298 }
10299 }
10300 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10301 /*
10302 * Derive by restriction.
10303 */
10304 if (baseIsAnyType) {
10305 type->attributeUses = uses;
10306 } else {
10307 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010308 const xmlChar *bEffValue;
10309 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010310
10311 cur = uses;
10312 while (cur != NULL) {
10313 found = 0;
10314 base = type->attributeUses;
10315 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010316 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10317 xmlSchemaGetAttrName(base->attr)) &&
10318 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10319 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010320
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010321 found = 1;
10322
Daniel Veillard3646d642004-06-02 19:19:14 +000010323 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10324 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10325 /*
10326 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010327 */
10328 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010329 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010330 NULL, type, NULL, cur->attr,
10331 "The 'optional' use is inconsistent with a matching "
10332 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010333 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10334 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10335 /*
10336 * derivation-ok-restriction 3
10337 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010338 xmlSchemaPCustomErr(ctxt,
10339 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10340 NULL, type, NULL,
10341 "A matching attribute use for the 'required' "
10342 "attribute use %s of the base type is missing",
10343 xmlSchemaFormatNsUriLocal(&str,
10344 xmlSchemaGetAttrTargetNsURI(base->attr),
10345 xmlSchemaGetAttrName(base->attr)));
10346 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010347 } else {
10348 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 * 2.1.3 [Definition:] Let the effective value
10350 * constraint of an attribute use be its {value
10351 * constraint}, if present, otherwise its {attribute
10352 * declaration}'s {value constraint} .
10353 */
10354 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10355 &bEffValue, 0);
10356 /*
10357 * 2.1.3 ... one of the following must be true
10358 *
10359 * 2.1.3.1 B's ·effective value constraint· is
10360 * ·absent· or default.
10361 */
10362 if ((bEffValue != NULL) &&
10363 (effFixed == 1)) {
10364 const xmlChar *rEffValue = NULL;
10365
10366 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10367 &rEffValue, 0);
10368 /*
10369 * 2.1.3.2 R's ·effective value constraint· is
10370 * fixed with the same string as B's.
10371 */
10372 if ((effFixed == 0) ||
10373 (! xmlStrEqual(rEffValue, bEffValue))) {
10374 xmlSchemaPAttrUseErr(ctxt,
10375 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10376 NULL, type, NULL, cur->attr,
10377 "The effective value constraint of the "
10378 "attribute use is inconsistent with "
10379 "its correspondent of the base type",
10380 NULL);
10381 }
10382 }
10383 /*
10384 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10385 */
10386 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010387 * Override the attribute use.
10388 */
10389 base->attr = cur->attr;
10390 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010391
Daniel Veillard3646d642004-06-02 19:19:14 +000010392 break;
10393 }
10394 base = base->next;
10395 }
10396
10397 if (!found) {
10398 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10399 /*
10400 * derivation-ok-restriction 2.2
10401 */
10402 if ((type->attributeWildcard != NULL) &&
10403 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10404 cur->attr->targetNamespace))
10405 found = 1;
10406
10407 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010408 xmlSchemaPAttrUseErr(ctxt,
10409 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10410 NULL, type, NULL, cur->attr,
10411 "Neither a matching attribute use, "
10412 "nor a matching wildcard in the base type does exist",
10413 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010414 } else {
10415 /*
10416 * Add the attribute use.
10417 *
10418 * Note that this may lead to funny derivation error reports, if
10419 * multiple equal attribute uses exist; but this is not
10420 * allowed anyway, and it will be reported beforehand.
10421 */
10422 tmp = cur;
10423 if (prev != NULL)
10424 prev->next = cur->next;
10425 else
10426 uses = cur->next;
10427 cur = cur->next;
10428 if (type->attributeUses == NULL) {
10429 type->attributeUses = tmp;
10430 } else
10431 lastBaseUse->next = tmp;
10432 lastBaseUse = tmp;
10433
10434 continue;
10435 }
10436 }
10437 }
10438 prev = cur;
10439 cur = cur->next;
10440 }
10441 if (uses != NULL)
10442 xmlSchemaFreeAttributeUseList(uses);
10443 }
10444 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10445 /*
10446 * The spec allows only appending, and not other kinds of extensions.
10447 *
10448 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10449 */
10450 if (uses != NULL) {
10451 if (type->attributeUses == NULL) {
10452 type->attributeUses = uses;
10453 } else
10454 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010455 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010456 } else {
10457 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010458 * Derive implicitely from the ur-type.
10459 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010460 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010461 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010462 /*
10463 * 3.4.6 -> Complex Type Definition Properties Correct
10464 */
10465 if (type->attributeUses != NULL) {
10466 cur = type->attributeUses;
10467 prev = NULL;
10468 while (cur != NULL) {
10469 /*
10470 * 4. Two distinct attribute declarations in the {attribute uses} must
10471 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010472 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010473 * Note that this was already done for "restriction" and types derived from
10474 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010475 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010476 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10477 tmp = cur->next;
10478 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010479 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10480 xmlSchemaGetAttrName(tmp->attr))) &&
10481 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10482 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010483
Daniel Veillardc0826a72004-08-10 14:17:33 +000010484 xmlSchemaPAttrUseErr(ctxt,
10485 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10486 NULL, type, NULL, tmp->attr,
10487 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010488 break;
10489 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010490 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010491 }
10492 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010493 /*
10494 * 5. Two distinct attribute declarations in the {attribute uses} must
10495 * not have {type definition}s which are or are derived from ID.
10496 */
10497 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010498 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010499 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010500 xmlSchemaPAttrUseErr(ctxt,
10501 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10502 NULL, type, NULL, cur->attr,
10503 "There must not exist more than one attribute use, "
10504 "declared of type 'ID' or derived from it",
10505 NULL);
10506 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010507 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010508 id = cur;
10509 }
10510 /*
10511 * Remove "prohibited" attribute uses. The reason this is done at this late
10512 * stage is to be able to catch dublicate attribute uses. So we had to keep
10513 * prohibited uses in the list as well.
10514 */
10515 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10516 tmp = cur;
10517 if (prev == NULL)
10518 type->attributeUses = cur->next;
10519 else
10520 prev->next = cur->next;
10521 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010522 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010523 } else {
10524 prev = cur;
10525 cur = cur->next;
10526 }
10527 }
10528 }
10529 /*
10530 * TODO: This check should be removed if we are 100% sure of
10531 * the base type attribute uses already being built.
10532 */
10533 if ((baseType != NULL) && (!baseIsAnyType) &&
10534 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10535 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010536 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010537 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010538 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010539 baseType->name, NULL);
10540 }
10541 return (0);
10542}
10543
10544/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010545 * xmlSchemaTypeFinalContains:
10546 * @schema: the schema
10547 * @type: the type definition
10548 * @final: the final
10549 *
10550 * Evaluates if a type definition contains the given "final".
10551 * This does take "finalDefault" into account as well.
10552 *
10553 * Returns 1 if the type does containt the given "final",
10554 * 0 otherwise.
10555 */
10556static int
10557xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10558{
10559 int tfinal = final, tflags = type->flags;
10560
10561 if (type == NULL)
10562 return (0);
10563 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10564 switch (final) {
10565 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10566 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10567 break;
10568 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10569 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10570 break;
10571 case XML_SCHEMAS_TYPE_FINAL_LIST:
10572 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10573 break;
10574 case XML_SCHEMAS_TYPE_FINAL_UNION:
10575 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10576 break;
10577 }
10578 tflags = schema->flags;
10579 }
10580 if (tflags & tfinal)
10581 return (1);
10582 else
10583 return (0);
10584
10585}
10586
10587/**
10588 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10589 * @type: the Union Simple Type
10590 *
10591 * Returns a list of member types of @type if existing,
10592 * returns NULL otherwise.
10593 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010594static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010595xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10596{
10597 while (type != NULL) {
10598 if (type->memberTypes != NULL)
10599 return (type->memberTypes);
10600 else
10601 type = type->baseType;
10602 }
10603 return (NULL);
10604}
10605
10606/**
10607 * xmlSchemaGetListSimpleTypeItemType:
10608 * @type: the simple type definition
10609 *
10610 * Returns the item type definition of the list simple type.
10611 */
10612static xmlSchemaTypePtr
10613xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10614{
10615 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10616 return (NULL);
10617 /*
10618 * Note: In libxml2, the built-in types do not reflect
10619 * the datatype hierarchy (yet?) - we have to treat them
10620 * in a special way.
10621 */
10622 if (type->type == XML_SCHEMA_TYPE_BASIC)
10623 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10624 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10625 /* 1 If the <list> alternative is chosen, then the type
10626 * definition ·resolved· to by the ·actual value· of the
10627 * itemType [attribute] of <list>, if present, otherwise
10628 * the type definition corresponding to the <simpleType>
10629 * among the [children] of <list>.
10630 */
10631 return (type->subtypes->subtypes);
10632 else {
10633 /* 2 If the <restriction> option is chosen, then the
10634 * {item type definition} of the {base type definition}.
10635 */
10636 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10637 }
10638}
10639
10640/**
10641 * xmlSchemaCheckCOSSTDerivedOK:
10642 * @type: the derived simple type definition
10643 * @baseType: the base type definition
10644 *
10645 * Checks wheter @type can be validly
10646 * derived from @baseType.
10647 *
10648 * Returns 0 on success, an positive error code otherwise.
10649 */
10650static int
10651xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10652 xmlSchemaTypePtr type,
10653 xmlSchemaTypePtr baseType,
10654 int subset)
10655{
10656 /*
10657 * Schema Component Constraint: Type Derivation OK (Simple)
10658 *
10659 *
10660 * 1 They are the same type definition.
10661 * TODO: The identy check might have to be more complex than this.
10662 */
10663 if (type == baseType)
10664 return (0);
10665 /*
10666 * 2.1 restriction is not in the subset, or in the {final}
10667 * of its own {base type definition};
10668 */
10669 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10670 (xmlSchemaTypeFinalContains(schema,
10671 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10672 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10673 }
10674 /* 2.2 */
10675 if (type->baseType == baseType) {
10676 /*
10677 * 2.2.1 D's ·base type definition· is B.
10678 */
10679 return (0);
10680 }
10681 /*
10682 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10683 * and is validly derived from B given the subset, as defined by this
10684 * constraint.
10685 */
10686 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10687 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10688 return (0);
10689 }
10690 /*
10691 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10692 * definition·.
10693 */
10694 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10695 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10696 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10697 return (0);
10698 }
10699 /*
10700 * 2.2.4 B's {variety} is union and D is validly derived from a type
10701 * definition in B's {member type definitions} given the subset, as
10702 * defined by this constraint.
10703 *
10704 * NOTE: This seems not to involve built-in types, since there is no
10705 * built-in Union Simple Type.
10706 */
10707 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10708 xmlSchemaTypeLinkPtr cur;
10709
10710 cur = baseType->memberTypes;
10711 while (cur != NULL) {
10712 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10713 cur->type, subset) == 0)
10714 return (0);
10715 cur = cur->next;
10716 }
10717 }
10718
10719 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10720}
10721
10722
10723/**
10724 * xmlSchemaCheckSTPropsCorrect:
10725 * @ctxt: the schema parser context
10726 * @type: the simple type definition
10727 *
10728 * Checks st-props-correct.
10729 *
10730 * Returns 0 if the properties are correct,
10731 * if not, a positive error code and -1 on internal
10732 * errors.
10733 */
10734static int
10735xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10736 xmlSchemaTypePtr type)
10737{
10738 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10739 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010740 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010741
Daniel Veillardc0826a72004-08-10 14:17:33 +000010742 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010743 /*
10744 * Schema Component Constraint: Simple Type Definition Properties Correct
10745 *
10746 * NOTE: This is somehow redundant, since we actually built a simple type
10747 * to have all the needed information; this acts as an self test.
10748 */
10749 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10750 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10751 /*
10752 * TODO: 1 The values of the properties of a simple type definition must be as
10753 * described in the property tableau in Datatype definition, modulo the
10754 * impact of Missing Sub-components (§5.3).
10755 */
10756 /* Base type: If the datatype has been ·derived· by ·restriction·
10757 * then the Simple Type Definition component from which it is ·derived·,
10758 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10759 */
10760 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010761 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010762 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010763 NULL, type, NULL,
10764 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010765 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10766 }
10767 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10768 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10769 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010770 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010771 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010772 NULL, type, NULL,
10773 "The base type %s is not a simple type",
10774 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10775 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010776 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10777 }
10778 if ((baseType != anySimpleType) &&
10779 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010780 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010781 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010782 NULL, type, NULL,
10783 "A type, derived by list or union, must have"
10784 "the simple ur-type definition as base type, not %s",
10785 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10786 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010787 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10788 }
10789 /*
10790 * Variety: One of {atomic, list, union}.
10791 */
10792 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10793 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10794 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010795 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010796 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010797 NULL, type, NULL,
10798 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010799 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10800 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010801 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010802
10803 /*
10804 * 2 All simple type definitions must be derived ultimately from the ·simple
10805 * ur-type definition (so· circular definitions are disallowed). That is, it
10806 * must be possible to reach a built-in primitive datatype or the ·simple
10807 * ur-type definition· by repeatedly following the {base type definition}.
10808 */
10809 baseType = type->baseType;
10810 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10811 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10812 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10813 if (baseType == anySimpleType)
10814 break;
10815 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010816 xmlSchemaPCustomErr(ctxt,
10817 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10818 NULL, type, NULL,
10819 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010820 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10821 }
10822 baseType = baseType->baseType;
10823 }
10824 /*
10825 * 3 The {final} of the {base type definition} must not contain restriction.
10826 */
10827 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10828 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010829 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010830 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010831 NULL, type, NULL,
10832 "The 'final' of its base type %s must not contain "
10833 "'restriction'",
10834 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10835 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010836 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10837 }
10838 return (0);
10839}
10840
10841/**
10842 * xmlSchemaCheckDerivationValidSimpleRestriction:
10843 * @ctxt: the schema parser context
10844 * @type: the simple type definition
10845 *
10846 * Checks if the given @type (simpleType) is derived
10847 * validly by restriction.
10848 *
10849 * Returns -1 on internal errors, 0 if the type is validly derived,
10850 * a positive error code otherwise.
10851 */
10852static int
10853xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010854 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010855{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010856 xmlChar *str = NULL;
10857
10858 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010859
10860 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10861 xmlSchemaPErr(ctxt, type->node,
10862 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010863 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10864 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010865 type->name, NULL);
10866 return (-1);
10867 }
10868
10869 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10870 xmlSchemaTypePtr primitive;
10871 /*
10872 * 1.1 The {base type definition} must be an atomic simple
10873 * type definition or a built-in primitive datatype.
10874 */
10875 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010876 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010877 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010878 NULL, type, NULL,
10879 "The base type %s is not an atomic simple type",
10880 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10881 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010882 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10883 }
10884 /* 1.2 The {final} of the {base type definition} must not contain
10885 * restriction.
10886 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010887 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010888 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10889 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010890 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010891 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010892 NULL, type, NULL,
10893 "The final of its base type %s must not contain 'restriction'",
10894 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10895 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010896 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10897 }
10898
10899 /*
10900 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10901 * type definition}, as specified in the appropriate subsection of 3.2
10902 * Primitive datatypes.
10903 */
10904 if (type->facets != NULL) {
10905 xmlSchemaFacetPtr facet;
10906 int ok = 1;
10907
10908 primitive = xmlSchemaGetPrimitiveType(type);
10909 if (primitive == NULL) {
10910 xmlSchemaPErr(ctxt, type->node,
10911 XML_ERR_INTERNAL_ERROR,
10912 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010913 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010914 type->name, NULL);
10915 return (-1);
10916 }
10917 facet = type->facets;
10918 do {
10919 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010920 ok = 0;
10921 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010922 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010923 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010924 }
10925 facet = facet->next;
10926 } while (facet != NULL);
10927 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010928 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010929 }
10930 /*
10931 * TODO: 1.3.2 (facet derivation)
10932 */
10933 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10934 xmlSchemaTypePtr itemType = NULL;
10935
10936 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10937 if (itemType == NULL) {
10938 xmlSchemaPErr(ctxt, type->node,
10939 XML_ERR_INTERNAL_ERROR,
10940 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010941 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010942 type->name, NULL);
10943 return (-1);
10944 }
10945 /*
10946 * 2.1 The {item type definition} must have a {variety} of atomic or
10947 * union (in which case all the {member type definitions}
10948 * must be atomic).
10949 */
10950 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10951 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010952 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010953 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010954 NULL, type, NULL,
10955 "The item type %s must have a variety of atomic or union",
10956 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10957 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010958 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10959 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10960 xmlSchemaTypeLinkPtr member;
10961
10962 member = itemType->memberTypes;
10963 while (member != NULL) {
10964 if ((member->type->flags &
10965 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010966 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010967 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010968 NULL, type, NULL,
10969 "The item type is a union type, but the "
10970 "member type %s of this item type is not atomic",
10971 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10972 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010973 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10974 }
10975 member = member->next;
10976 }
10977 }
10978
10979 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10980 xmlSchemaFacetPtr facet;
10981 /*
10982 * This is the case if we have: <simpleType><list ..
10983 */
10984 /*
10985 * 2.3.1
10986 * 2.3.1.1 The {final} of the {item type definition} must not
10987 * contain list.
10988 */
10989 if (xmlSchemaTypeFinalContains(ctxt->schema,
10990 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010991 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010992 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010993 NULL, type, NULL,
10994 "The final of its item type %s must not contain 'list'",
10995 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10996 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010997 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10998 }
10999 /*
11000 * 2.3.1.2 The {facets} must only contain the whiteSpace
11001 * facet component.
11002 */
11003 if (type->facets != NULL) {
11004 facet = type->facets;
11005 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011006 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11007 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011008 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011009 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011010 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11011 }
11012 facet = facet->next;
11013 } while (facet != NULL);
11014 }
11015 /*
11016 * TODO: Datatypes states:
11017 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11018 * whose ·lexical space· allows space (such as string or anyURI)or
11019 * a ·union· datatype any of whose {member type definitions}'s
11020 * ·lexical space· allows space.
11021 */
11022 } else {
11023 /*
11024 * This is the case if we have: <simpleType><restriction ...
11025 */
11026 /*
11027 * 2.3.2
11028 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11029 */
11030 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011031 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011032 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011033 NULL, type, NULL,
11034 "The base type %s must be a list type",
11035 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11036 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011037 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11038 }
11039 /*
11040 * 2.3.2.2 The {final} of the {base type definition} must not
11041 * contain restriction.
11042 */
11043 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11044 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011045 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011046 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011047 NULL, type, NULL,
11048 "The final of the base type %s must not contain 'restriction'",
11049 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11050 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011051 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11052 }
11053 /*
11054 * 2.3.2.3 The {item type definition} must be validly derived
11055 * from the {base type definition}'s {item type definition} given
11056 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11057 */
11058 {
11059 xmlSchemaTypePtr baseItemType;
11060
11061 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11062 if (baseItemType == NULL) {
11063 xmlSchemaPErr(ctxt, type->node,
11064 XML_ERR_INTERNAL_ERROR,
11065 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011066 "List simple type '%s': Failed to "
11067 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011068 type->name, type->baseType->name);
11069 return (-1);
11070 }
11071 if ((itemType != baseItemType) &&
11072 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11073 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011074 xmlChar *strBIT = NULL, *strBT = NULL;
11075 xmlSchemaPCustomErrExt(ctxt,
11076 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11077 NULL, type, NULL,
11078 "The item type %s is not validly derived from the "
11079 "item type %s of the base type %s",
11080 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11081 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11082 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11083
11084 FREE_AND_NULL(str)
11085 FREE_AND_NULL(strBIT)
11086 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011087 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11088 }
11089 }
11090
11091 if (type->facets != NULL) {
11092 xmlSchemaFacetPtr facet;
11093 int ok = 1;
11094 /*
11095 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11096 * and enumeration facet components are allowed among the {facets}.
11097 */
11098 facet = type->facets;
11099 do {
11100 switch (facet->type) {
11101 case XML_SCHEMA_FACET_LENGTH:
11102 case XML_SCHEMA_FACET_MINLENGTH:
11103 case XML_SCHEMA_FACET_MAXLENGTH:
11104 case XML_SCHEMA_FACET_WHITESPACE:
11105 /*
11106 * TODO: 2.5.1.2 List datatypes
11107 * The value of ·whiteSpace· is fixed to the value collapse.
11108 */
11109 case XML_SCHEMA_FACET_PATTERN:
11110 case XML_SCHEMA_FACET_ENUMERATION:
11111 break;
11112 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011113 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011114 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011115 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011116 /*
11117 * We could return, but it's nicer to report all
11118 * invalid facets.
11119 */
11120 ok = 0;
11121 }
11122 }
11123 facet = facet->next;
11124 } while (facet != NULL);
11125 if (ok == 0)
11126 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11127 /*
11128 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11129 * is a facet of the same kind in the {facets} of the {base type
11130 * definition} (call this BF),then the DF's {value} must be a valid
11131 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11132 */
11133 }
11134
11135
11136 }
11137 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11138 /*
11139 * 3.1 The {member type definitions} must all have {variety} of
11140 * atomic or list.
11141 */
11142 xmlSchemaTypeLinkPtr member;
11143
11144 member = type->memberTypes;
11145 while (member != NULL) {
11146 if (((member->type->flags &
11147 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11148 ((member->type->flags &
11149 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011150 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011151 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011152 NULL, type, NULL,
11153 "The member type %s is neither an atomic, nor a list type",
11154 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11155 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011156 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11157 }
11158 member = member->next;
11159 }
11160 /*
11161 * 3.3.1 If the {base type definition} is the ·simple ur-type
11162 * definition·
11163 */
11164 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11165 /*
11166 * 3.3.1.1 All of the {member type definitions} must have a
11167 * {final} which does not contain union.
11168 */
11169 member = type->memberTypes;
11170 while (member != NULL) {
11171 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11172 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011173 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011174 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011175 NULL, type, NULL,
11176 "The final of member type %s contains 'union'",
11177 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11178 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011179 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11180 }
11181 member = member->next;
11182 }
11183 /*
11184 * 3.3.1.2 The {facets} must be empty.
11185 */
11186 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011187 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011188 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011189 NULL, type, NULL,
11190 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011191 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11192 }
11193 } else {
11194 /*
11195 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11196 */
11197 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011198 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011199 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011200 NULL, type, NULL,
11201 "The base type %s is not a union type",
11202 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11203 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011204 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11205 }
11206 /*
11207 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11208 */
11209 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11210 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011211 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011212 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011213 NULL, type, NULL,
11214 "The final of its base type %s must not contain 'restriction'",
11215 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11216 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011217 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11218 }
11219 /*
11220 * 3.3.2.3 The {member type definitions}, in order, must be validly
11221 * derived from the corresponding type definitions in the {base
11222 * type definition}'s {member type definitions} given the empty set,
11223 * as defined in Type Derivation OK (Simple) (§3.14.6).
11224 */
11225 {
11226 xmlSchemaTypeLinkPtr baseMember;
11227
11228 /*
11229 * OPTIMIZE: if the type is restricting, it has no local defined
11230 * member types and inherits the member types of the base type;
11231 * thus a check for equality can be skipped.
11232 */
11233 /*
11234 * TODO: Even worse: I cannot see a scenario where a restricting
11235 * union simple type can have other member types as the member
11236 * types of it's base type. This check seems not necessary with
11237 * respect to the derivation process in libxml2.
11238 */
11239 if (type->memberTypes != NULL) {
11240 member = type->memberTypes;
11241 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11242 if ((member == NULL) && (baseMember != NULL)) {
11243 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011244 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011245 "Internal error: "
11246 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011247 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011248 "of member types in the base type\n",
11249 type->name, NULL);
11250 }
11251 while (member != NULL) {
11252 if (baseMember == NULL) {
11253 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011254 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011255 "Internal error: "
11256 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011257 "(3.3.2.3), union simple type '%s', unequal number "
11258 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011259 type->name, NULL);
11260 }
11261 if ((member->type != baseMember->type) &&
11262 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11263 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011264 xmlChar *strBMT = NULL, *strBT = NULL;
11265
11266 xmlSchemaPCustomErrExt(ctxt,
11267 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11268 NULL, type, NULL,
11269 "The member type %s is not validly derived from its "
11270 "corresponding member type %s of the base type %s",
11271 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11272 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11273 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11274 FREE_AND_NULL(str)
11275 FREE_AND_NULL(strBMT)
11276 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011277 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11278 }
11279 member = member->next;
11280 baseMember = baseMember->next;
11281 }
11282 }
11283 }
11284 /*
11285 * 3.3.2.4 Only pattern and enumeration facet components are
11286 * allowed among the {facets}.
11287 */
11288 if (type->facets != NULL) {
11289 xmlSchemaFacetPtr facet;
11290 int ok = 1;
11291
11292 facet = type->facets;
11293 do {
11294 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11295 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011296 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11297 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11298 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011299 ok = 0;
11300 }
11301 facet = facet->next;
11302 } while (facet != NULL);
11303 if (ok == 0)
11304 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11305
11306 }
11307 /*
11308 * TODO: 3.3.2.5 (facet derivation)
11309 */
11310 }
11311 }
11312
11313 return (0);
11314}
11315
11316/**
11317 * xmlSchemaCheckSRCSimpleType:
11318 * @ctxt: the schema parser context
11319 * @type: the simple type definition
11320 *
11321 * Checks crc-simple-type constraints.
11322 *
11323 * Returns 0 if the constraints are satisfied,
11324 * if not a positive error code and -1 on internal
11325 * errors.
11326 */
11327static int
11328xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11329 xmlSchemaTypePtr type)
11330{
11331 /*
11332 * NOTE: src-simple-type 2-4 are redundant, since the checks
11333 * were are done for the corresponding <restriction>, <list> and <union>
11334 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11335 * Maby this can be skipped in the future, if we get sure it's not needed.
11336 */
11337 if (type->subtypes == NULL) {
11338 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011339 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011340 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011341 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011342 type->name, NULL);
11343 return (-1);
11344 }
11345 /*
11346 * src-simple-type.1 The corresponding simple type definition, if any,
11347 * must satisfy the conditions set out in Constraints on Simple Type
11348 * Definition Schema Components (§3.14.6).
11349 */
11350 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11351 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11352 /*
11353 * TODO: Removed this, since it got annoying to get an
11354 * extra error report, if anything failed until now.
11355 * Enable this if needed.
11356 */
11357 /*
11358 xmlSchemaPErr(ctxt, type->node,
11359 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011360 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011361 "on simple type definitions.\n",
11362 type->name, NULL);
11363 */
11364 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11365 }
11366
11367 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11368 /*
11369 * src-simple-type.2 If the <restriction> alternative is chosen,
11370 * either it must have a base [attribute] or a <simpleType> among its
11371 * [children], but not both.
11372 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011373 /*
11374 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11375 * NOTE: This was removed, since this will be already handled
11376 * in the parse function for <restriction>.
11377 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011378 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11379 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11380 * an itemType [attribute] or a <simpleType> among its [children],
11381 * but not both.
11382 * NOTE: baseType is set to the local simple type definiton,
11383 * if existent, at parse time. This is a hack and not nice.
11384 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011385 /*
11386 * TODO: Remove this, and add the check to the parse function of <list>.
11387 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011388 if (((type->subtypes->base == NULL) &&
11389 (type->baseType == NULL)) ||
11390 ((type->subtypes->base != NULL) &&
11391 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011392 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011393 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011394 NULL, type, NULL,
11395 "Either the attribute 'itemType' or the <simpleType> child "
11396 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011397 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11398 }
11399
11400
11401 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11402 xmlSchemaTypeLinkPtr member;
11403 xmlSchemaTypePtr ancestor, anySimpleType;
11404
11405 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11406
11407 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11408 * the <union> alternative is chosen, there must not be any entries
11409 * in the memberTypes [attribute] at any depth which resolve to the
11410 * component corresponding to the <simpleType>.
11411 */
11412 member = type->memberTypes;
11413 while (member != NULL) {
11414 ancestor = member->type;
11415 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11416 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11417 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11418 if (ancestor == anySimpleType)
11419 break;
11420 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011421 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011422 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011423 NULL, type, NULL,
11424 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011425 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11426 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11427 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011428 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011429 * type as item type, which in turn has a list ST as member
11430 * type, we will assume this here as well, since this check
11431 * was not yet performed.
11432 */
11433
11434 }
11435 ancestor = ancestor->baseType;
11436 }
11437 member = member->next;
11438 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011439 }
11440
11441 return (0);
11442}
11443
William M. Brack2f2a6632004-08-20 23:09:47 +000011444#if 0 /* Not yet used code for CT schema validation */
11445static int
11446xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11447 const xmlChar * value,
11448 xmlSchemaTypePtr type,
11449 int fireErrors)
11450{
11451 int ret;
11452 /*
11453 * 3.14.4 Simple Type Definition Validation Rules
11454 * Validation Rule: String Valid
11455 */
11456 /*
11457 * 1 It is schema-valid with respect to that definition as defined
11458 * by Datatype Valid in [XML Schemas: Datatypes].
11459 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011460 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11461 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011462 return (ret);
11463 /*
11464 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11465 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11466 * the string must be a ·declared entity name·.
11467 */
11468 /*
11469 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11470 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11471 * then every whitespace-delimited substring of the string must be a ·declared
11472 * entity name·.
11473 */
11474 /*
11475 * 2.3 otherwise no further condition applies.
11476 */
11477
11478 return (0);
11479}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011480#endif
11481
William M. Brack2f2a6632004-08-20 23:09:47 +000011482
11483static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011484xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11485{
11486 if (vctxt->pctxt == NULL) {
11487 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11488 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11489 if (vctxt->pctxt == NULL) {
11490 xmlSchemaVErr(vctxt, NULL,
11491 XML_SCHEMAV_INTERNAL,
11492 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11493 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011494 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011495 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011496 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011497 /* TODO: Pass user data. */
11498 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11499 }
11500 return (0);
11501}
11502
11503static int
11504xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11505{
11506 if (ctxt->vctxt == NULL) {
11507 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11508 if (ctxt->vctxt == NULL) {
11509 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011510 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011511 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11512 "failed to create a temp. validation context.\n",
11513 NULL, NULL);
11514 return (-1);
11515 }
11516 /* TODO: Pass user data. */
11517 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11518 }
11519 return (0);
11520}
11521
11522/**
11523 * xmlSchemaCheckCOSValidDefault:
11524 * @ctxt: the schema parser context
11525 * @type: the simple type definition
11526 * @value: the default value
11527 * @node: an optional node (the holder of the value)
11528 *
11529 * Checks the "cos-valid-default" constraints.
11530 *
11531 * Returns 0 if the constraints are satisfied,
11532 * if not, a positive error code and -1 on internal
11533 * errors.
11534 */
11535static int
11536xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11537 xmlSchemaValidCtxtPtr vctxt,
11538 xmlSchemaTypePtr type,
11539 const xmlChar *value,
11540 xmlNodePtr node)
11541{
11542 int ret = 0;
11543
11544 /*
11545 * cos-valid-default:
11546 * Schema Component Constraint: Element Default Valid (Immediate)
11547 * For a string to be a valid default with respect to a type
11548 * definition the appropriate case among the following must be true:
11549 */
11550 /*
11551 * NOTE: This has to work without a given node (the holder of the
11552 * value), since it should work on the component, i.e. an underlying
11553 * DOM must not be mandatory.
11554 */
11555 if ((pctxt == NULL) || (vctxt == NULL)) {
11556 xmlSchemaPErr(pctxt, node,
11557 XML_SCHEMAP_INTERNAL,
11558 "Internal error: xmlSchemaCheckCOSValidDefault, "
11559 "bad arguments: the parser and/or validation context is "
11560 "missing.\n",
11561 NULL, NULL);
11562 return (-1);
11563 }
11564 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011565 /*
11566 * Complex type.
11567 *
11568 * 2.1 its {content type} must be a simple type definition or mixed.
11569 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011570 /*
11571 * TODO: Adjust this when the content type will be computed
11572 * correctly.
11573 */
11574 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11575 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11576 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11577 xmlSchemaPSimpleTypeErr(pctxt,
11578 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11579 NULL, NULL, node,
11580 type, NULL, NULL,
11581 "If the type of a constraint value is complex, its content "
11582 "type must be mixed or a simple type",
11583 NULL, NULL);
11584 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11585 }
11586 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011587 /*
11588 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11589 * particle must be ·emptiable· as defined by Particle Emptiable
11590 * (§3.9.6).
11591 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011592
William M. Brack2f2a6632004-08-20 23:09:47 +000011593 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011594 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011595 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011596 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011597 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011598 }
11599 /*
11600 * 1 If the type definition is a simple type definition, then the string
11601 * must be ·valid· with respect to that definition as defined by String
11602 * Valid (§3.14.4).
11603 *
11604 * AND
11605 *
11606 * 2.2.1 If the {content type} is a simple type definition, then the
11607 * string must be ·valid· with respect to that simple type definition
11608 * as defined by String Valid (§3.14.4).
11609 */
11610 vctxt->node = node;
11611 vctxt->cur = NULL;
11612 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11613 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11614 if (ret < 0) {
11615 xmlSchemaPErr(pctxt, node,
11616 /* NOTNICE: error code: This function will be used during
11617 * schema construction and xsi:type validation.
11618 */
11619 XML_SCHEMAP_INTERNAL,
11620 "Internal error: xmlSchemaCheckCOSValidDefault, "
11621 "while validating a value constaint value.\n",
11622 NULL, NULL);
11623
11624 }
11625 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011626}
11627
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011628#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011629/**
11630 * xmlSchemaGetSTContentOfCT:
11631 * @ctxt: the schema parser context
11632 * @type: the complex type definition
11633 *
11634 *
11635 * Returns the corresponding simple type for the content of
11636 * the complex type.
11637 */
11638static xmlSchemaTypePtr
11639xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11640 xmlSchemaTypePtr type)
11641{
11642 xmlSchemaTypePtr orig = type, anyType;
11643
11644 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11645 while ((type != NULL) && (type != anyType) &&
11646 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11647 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11648 return(type);
11649 type = type->baseType;
11650 }
11651 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011652 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011653 NULL, orig, NULL,
11654 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11655 "no simple type for the content of complex type '%s' could be "
11656 "computed", orig->name);
11657 return (NULL);
11658}
11659
11660
William M. Brack2f2a6632004-08-20 23:09:47 +000011661
William M. Brack2f2a6632004-08-20 23:09:47 +000011662
11663/**
11664 * xmlSchemaCheckCOSCTExtends:
11665 * @ctxt: the schema parser context
11666 * @type: the complex type definition
11667 *
11668 * Schema Component Constraint: Derivation Valid (Extension)
11669 *
11670 * Returns 0 if the constraints are satisfied, a positive
11671 * error code if not and -1 if an internal error occured.
11672 */
11673static int
11674xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11675 xmlSchemaTypePtr type)
11676{
11677 xmlSchemaTypePtr base;
11678 /*
11679 * 1 If the {base type definition} is a complex type definition,
11680 * then all of the following must be true:
11681 */
11682 base = type->baseType;
11683 if (base == NULL) {
11684 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011685 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011686 NULL, type, NULL,
11687 "Internal error: xmlSchemaCheckCOSCTExtends, "
11688 "the complex type '%s' has no base type", type->name);
11689 return (-1);
11690 }
11691 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11692 /*
11693 * 1.1 The {final} of the {base type definition} must not
11694 * contain extension.
11695 */
11696 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11697 xmlSchemaPCustomErr(ctxt,
11698 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11699 NULL, type, NULL,
11700 "The 'final' of the base type definition "
11701 "contains extension", NULL);
11702 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11703 }
11704 /*
11705 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11706 * of the complex type definition itself, that is, for every attribute
11707 * use in the {attribute uses} of the {base type definition}, there
11708 * must be an attribute use in the {attribute uses} of the complex
11709 * type definition itself whose {attribute declaration} has the same
11710 * {name}, {target namespace} and {type definition} as its attribute
11711 * declaration
11712 *
11713 * NOTE: This will be already satisfied by the way the attribute uses
11714 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11715 * is not needed.
11716 */
11717
11718 /*
11719 * 1.3 If it has an {attribute wildcard}, the complex type definition
11720 * must also have one, and the base type definition's {attribute
11721 * wildcard}'s {namespace constraint} must be a subset of the complex
11722 * type definition's {attribute wildcard}'s {namespace constraint},
11723 * as defined by Wildcard Subset (§3.10.6).
11724 *
11725 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11726 * this check is not needed.
11727 */
11728
11729 /*
11730 * 1.4 One of the following must be true:
11731 *
11732 * 1.4.1 The {content type} of the {base type definition} and the
11733 * {content type} of the complex type definition itself must be the same
11734 * simple type definition
11735 */
11736
11737
11738
11739 } else {
11740 /*
11741 * 2 If the {base type definition} is a simple type definition,
11742 * then all of the following must be true:
11743 */
11744 /*
11745 * 2.1 The {content type} must be the same simple type definition.
11746 */
11747 /*
11748 * 2.2 The {final} of the {base type definition} must not contain
11749 * extension
11750 */
11751 }
11752
11753}
11754
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011755static int
11756xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11757 xmlSchemaTypePtr type)
11758{
11759 xmlSchemaTypePtr base, content;
11760 int OK = 0;
11761
11762 /*
11763 * TODO: Adjust the error codes here, as I used
11764 * XML_SCHEMAP_SRC_CT_1 only yet.
11765 */
11766 /*
11767 * Schema Representation Constraint:
11768 * Complex Type Definition Representation OK
11769 */
11770 base = type->baseType;
11771 if (base == NULL) {
11772 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11773 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11774 type->name);
11775 return (-1);
11776 }
11777
11778 if (type->subtypes != NULL) {
11779 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11780 if IS_COMPLEX_TYPE(base) {
11781 /*
11782 * 1 If the <complexContent> alternative is chosen, the type definition
11783 * ·resolved· to by the ·actual value· of the base [attribute]
11784 * must be a complex type definition;
11785 */
11786 xmlSchemaPCustomErr(ctxt,
11787 XML_SCHEMAP_SRC_CT_1,
11788 NULL, type, NULL,
11789 "The base type is not a complex type", NULL);
11790 return (XML_SCHEMAP_SRC_CT_1);
11791 }
11792 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11793
11794 if IS_SIMPLE_TYPE(base) {
11795 if (type->flags &
11796 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11797 /*
11798 * 2.1.3 only if the <extension> alternative is also
11799 * chosen, a simple type definition.
11800 */
11801 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11802 xmlSchemaPCustomErr(ctxt,
11803 XML_SCHEMAP_SRC_CT_1,
11804 NULL, type, NULL,
11805 "A complex type (simple content) cannot restrict "
11806 "an other simple type",
11807 NULL);
11808 return (XML_SCHEMAP_SRC_CT_1);
11809 }
11810 OK = 1;
11811
11812 } else { /* if IS_SIMPLE_TYPE(base) */
11813 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11814 /*
11815 * 2.1.2 only if the <restriction> alternative is also
11816 * chosen, a complex type definition whose {content type}
11817 * is mixed and a particle emptyable.
11818 */
11819 /*
11820 * FIXME TODO: Check for *empiable particle* is missing.
11821 */
11822 if ((type->flags &
11823 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11824 xmlSchemaPCustomErr(ctxt,
11825 XML_SCHEMAP_SRC_CT_1,
11826 NULL, type, NULL,
11827 "A complex type (simple content) cannot "
11828 "extend an other complex type which has a "
11829 "content type of: 'mixed' and emptiable particle",
11830 NULL);
11831 return (XML_SCHEMAP_SRC_CT_1);
11832 }
11833 /*
11834 * NOTE: This will be fired as well, if the base type
11835 * is *'anyType'*.
11836 * NOTE: type->subtypes->subtypes will be the
11837 * <restriction> item.
11838 */
11839 if (type->subtypes->subtypes == NULL) {
11840 /* Yes, this is paranoid programming. */
11841 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11842 NULL, type, NULL,
11843 "Internal error: xmlSchemaCheckSRCCT, "
11844 "'%s', <simpleContent> has no <restriction>",
11845 type->name);
11846 return (-1);
11847 }
11848 /*
11849 * 2.2 If clause 2.1.2 above is satisfied, then there
11850 * must be a <simpleType> among the [children] of
11851 * <restriction>.
11852 */
11853 if (type->subtypes->subtypes->type !=
11854 XML_SCHEMA_TYPE_SIMPLE) {
11855 /* TODO: Change error code to ..._SRC_CT_2_2. */
11856 xmlSchemaPCustomErr(ctxt,
11857 XML_SCHEMAP_SRC_CT_1,
11858 NULL, type, NULL,
11859 "A <simpleType> is expected among the children "
11860 "of <restriction>", NULL);
11861 return (XML_SCHEMAP_SRC_CT_1);
11862 }
11863 OK = 1;
11864 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
11865 /*
11866 * 2.1.1 a complex type definition whose {content type} is a
11867 * simple type definition;
11868 */
11869 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
11870 xmlSchemaPCustomErr(ctxt,
11871 XML_SCHEMAP_SRC_CT_1,
11872 NULL, type, NULL,
11873 "A complex type (simple content) cannot "
11874 "be derived from the complex type '%s'",
11875 base->name);
11876 return (XML_SCHEMAP_SRC_CT_1);
11877 }
11878 content = base->contentTypeDef;
11879 if (content == NULL) {
11880 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11881 NULL, type, NULL,
11882 "Internal error: xmlSchemaCheckSRCCT, "
11883 "'%s', base type has no content type",
11884 type->name);
11885 return (-1);
11886 }
11887 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
11888 xmlSchemaPCustomErr(ctxt,
11889 XML_SCHEMAP_SRC_CT_1,
11890 NULL, type, NULL,
11891 "A complex type (simple content) cannot "
11892 "be derived from the complex type '%s'",
11893 base->name);
11894 return (XML_SCHEMAP_SRC_CT_1);
11895 }
11896 }
11897 }
11898 }
11899 }
11900 /*
11901 * TODO: 3 The corresponding complex type definition component must
11902 * satisfy the conditions set out in Constraints on Complex Type
11903 * Definition Schema Components (§3.4.6);
11904 *
11905 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
11906 * above for {attribute wildcard} is satisfied, the intensional
11907 * intersection must be expressible, as defined in Attribute Wildcard
11908 * Intersection (§3.10.6).
11909 */
11910
11911}
William M. Brack2f2a6632004-08-20 23:09:47 +000011912#endif
11913
Daniel Veillard01fa6152004-06-29 17:04:39 +000011914/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011915 * xmlSchemaGroupDefFixup:
11916 * @typeDecl: the schema model group definition
11917 * @ctxt: the schema parser context
11918 *
11919 * Fixes model group definitions.
11920 */
11921static void
11922xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11923 xmlSchemaParserCtxtPtr ctxt,
11924 const xmlChar * name ATTRIBUTE_UNUSED)
11925{
11926 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11927 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11928 xmlSchemaTypePtr groupDef;
11929 /*
11930 * Resolve the reference.
11931 */
11932 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11933 group->refNs);
11934 if (groupDef == NULL) {
11935 xmlSchemaPResCompAttrErr(ctxt,
11936 XML_SCHEMAP_SRC_RESOLVE,
11937 NULL, group, NULL,
11938 "ref", group->ref, group->refNs,
11939 XML_SCHEMA_TYPE_GROUP, NULL);
11940 return;
11941 }
11942 group->subtypes = groupDef;
11943 }
11944}
11945
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011946#if 0 /* Enable when the content type will be computed. */
11947static int
11948xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
11949 xmlSchemaTypePtr type)
11950{
11951 xmlSchemaTypePtr base, res = NULL;
11952
11953 base = type->baseType;
11954 if (base == NULL) {
11955 xmlSchemaPCustomErr(ctxt,
11956 XML_SCHEMAP_INTERNAL,
11957 NULL, type, NULL,
11958 "Internal error: xmlSchemaGetContentType, "
11959 "the complex type '%s' has no base type", type->name);
11960 return (-1);
11961 }
11962 if (IS_ANYTYPE(base) || (type->subtypes->type ==
11963 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
11964 xmlSchemaTypePtr start;
11965 /*
11966 * Effective 'mixed'.
11967 */
11968 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
11969 type->contentType = XML_SCHEMA_CONTENT_MIXED;
11970 /*
11971 * Effective content.
11972 */
11973 if (IS_ANYTYPE(base))
11974 start = type;
11975 else
11976 start = type->subtypes;
11977
11978 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
11979 xmlSchemaTypePtr baseContentItem;
11980
11981 /*
11982 * Complex type with simple content.
11983 */
11984 if IS_COMPLEX_TYPE(base) {
11985 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11986 /*
11987 * Summary: a complex type (simple content) can *restrict*
11988 * a complex type with the following content type:
11989 * 1. 'mixed' and an emptiable particle
11990 * 2. simple type
11991 */
11992 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
11993 /*
11994 * 2 if the {content type} of the base type is mixed and a
11995 * particle which is ·emptiable·,
11996 * [...]
11997 * then starting from the simple type definition
11998 * corresponding to the <simpleType> among the [children]
11999 * of <restriction> (**which must be present**)
12000 *
12001 * FIXME TODO: Handle "emptiable particle".
12002 */
12003 res = type->subtypes->subtypes;
12004 if (res == NULL) {
12005 xmlSchemaPCustomErr(ctxt,
12006 XML_SCHEMAP_INTERNAL,
12007 NULL, type, NULL,
12008 "Internal error: xmlSchemaGetContentType, "
12009 "CT '%s' (restricting): <simpleContent> has no "
12010 "<restriction>",
12011 type->name);
12012 return (-1);
12013 }
12014
12015 res->subtypes;
12016 if (res == NULL) {
12017 xmlSchemaPCustomErr(ctxt,
12018 XML_SCHEMAP_INTERNAL,
12019 NULL, type, NULL,
12020 "Internal error: xmlSchemaGetContentType, "
12021 "CT '%s' (restricting): <restriction> has no "
12022 "mandatory <simpleType>",
12023 type->name);
12024 return (-1);
12025 }
12026 } else {
12027 baseContentItem = base->contentTypeDef;
12028 if (baseContentItem == NULL) {
12029 xmlSchemaPCustomErr(ctxt,
12030 XML_SCHEMAP_INTERNAL,
12031 NULL, type, NULL,
12032 "Internal error: xmlSchemaGetContentType, "
12033 "CT '%s' (restricting), the base type has no "
12034 "content type", type->name);
12035 return (-1);
12036 }
12037 if IS_SIMPLE_TYPE(baseContentItem) {
12038 /*
12039 * 1 If the base type is a complex type whose own
12040 * {content type} is a simple type and the <restriction>
12041 * alternative is chosen
12042 */
12043 /* type->subtypes->subtypes will be the restriction item.*/
12044 res = type->subtypes->subtypes;
12045 if (res == NULL) {
12046 xmlSchemaPCustomErr(ctxt,
12047 XML_SCHEMAP_INTERNAL,
12048 NULL, type, NULL,
12049 "Internal error: xmlSchemaGetContentType, "
12050 "CT '%s' (restricting): <simpleType> has no "
12051 "<restriction>", type->name);
12052 return (-1);
12053 }
12054 /*
12055 * 1.1 the simple type definition corresponding to the
12056 * <simpleType> among the [children] of <restriction>if
12057 * there is one;
12058 */
12059 res = res->subtypes;
12060 if (res == NULL) {
12061 /*
12062 * 1.2 otherwise the {content type}
12063 * of the base type .
12064 */
12065 res = baseContentItem;
12066 }
12067 }
12068 }
12069 /*
12070 * SPECIAL TODO: If *restricting* the spec wants us to
12071 * create an *additional* simple type which restricts the
12072 * located simple type; we won't do this yet, and look how
12073 * far we get with it.
12074 */
12075 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12076 /*
12077 * Summary: a complex type (simple content) can *extend*
12078 * only a complex base with a simple type as content.
12079 */
12080 /*
12081 * 3 If the type definition ·resolved· to by the ·actual
12082 * value· of the base [attribute] is a complex type
12083 * definition (whose own {content type} *must be* a simple
12084 * type definition, see below) and the *<extension>*
12085 * alternative is chosen, then the {content type} of that
12086 * complex type definition;
12087 */
12088 res = base->contentTypeDef;
12089 if (res == NULL) {
12090 xmlSchemaPCustomErr(ctxt,
12091 XML_SCHEMAP_INTERNAL,
12092 NULL, type, NULL,
12093 "Internal error: xmlSchemaGetContentType, "
12094 "CT '%s' (extending), the base type has no content "
12095 "type", type->name);
12096 return (-1);
12097 }
12098 if (! IS_SIMPLE_TYPE(res)) {
12099 xmlSchemaPCustomErr(ctxt,
12100 XML_SCHEMAP_INTERNAL,
12101 NULL, type, NULL,
12102 "Internal error: xmlSchemaGetContentType, "
12103 "CT '%s' (extending), the content type of the "
12104 "base is not a simple type", type->name);
12105 return (-1);
12106 }
12107 }
12108 } else /* if IS_COMPLEX_TYPE(base) */
12109 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12110 /*
12111 * 4 otherwise (the type definition ·resolved· to by the
12112 * ·actual value· of the base [attribute] is a simple type
12113 * definition and the <extension> alternative is chosen),
12114 * then that simple type definition.
12115 */
12116 res = base;
12117 }
12118 type->contentTypeDef = res;
12119 if (res == NULL) {
12120 xmlSchemaPCustomErr(ctxt,
12121 XML_SCHEMAP_INTERNAL,
12122 NULL, type, NULL,
12123 "Internal error: xmlSchemaGetContentType, "
12124 "'%s', the content type could not be determined",
12125 type->name);
12126 return (-1);
12127 }
12128
12129 }
12130
12131}
12132#endif
12133
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012134/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012135 * xmlSchemaTypeFixup:
12136 * @typeDecl: the schema type definition
12137 * @ctxt: the schema parser context
12138 *
12139 * Fixes the content model of the type.
12140 */
12141static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012142xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012143 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012144{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012145 xmlSchemaTypePtr ctxtType;
12146
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012147 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012148 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012149 /*
12150 * Do not allow the following types to be typefixed, prior to
12151 * the corresponding simple/complex types.
12152 */
12153 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012154 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012155 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12156 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12157 case XML_SCHEMA_TYPE_UNION:
12158 case XML_SCHEMA_TYPE_RESTRICTION:
12159 case XML_SCHEMA_TYPE_EXTENSION:
12160 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012161 default:
12162 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012163 }
12164 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012165 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012166 name = item->name;
12167 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12168 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012169 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012170 if (item->subtypes != NULL) {
12171 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012172 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012173 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012174 NULL);
12175 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012176 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012177 XML_SCHEMA_CONTENT_SIMPLE;
12178 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012179 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012180 break;
12181 }
12182 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012183 xmlSchemaTypePtr base = NULL;
12184
12185 ctxt->ctxtType->flags |=
12186 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012187 if (item->baseType != NULL)
12188 base = item->baseType;
12189 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012190 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012191 xmlSchemaGetType(ctxt->schema, item->base,
12192 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012193 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012194 xmlSchemaPResCompAttrErr(ctxt,
12195 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012196 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012197 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12198 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012199 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012200 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012201 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012202 xmlSchemaTypeFixup(base, ctxt, NULL);
12203 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012204 }
12205 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012206 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12207 /*
12208 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012209 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012210 /*
12211 * Content type.
12212 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012213 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012214 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012215 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12216 else if ((item->subtypes->subtypes == NULL) &&
12217 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012218 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012219 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012220 XML_SCHEMA_TYPE_SEQUENCE)))
12221 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012222 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12223 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012224 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012225 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012226 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012227 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012228 else {
12229 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012230 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012231 XML_SCHEMA_CONTENT_ELEMENTS;
12232 }
12233 } else {
12234 /*
12235 * SimpleType restriction.
12236 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012237 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012238 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012239 break;
12240 }
12241 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012242 xmlSchemaTypePtr base = NULL;
12243 xmlSchemaContentType explicitContentType;
12244
12245 /*
12246 * An extension does exist on a complexType only.
12247 */
12248 ctxt->ctxtType->flags |=
12249 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012250 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012251 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012252 xmlSchemaPCustomErr(ctxt,
12253 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012254 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012255 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012256 return;
12257 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012258 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012259 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012260 xmlSchemaGetType(ctxt->schema, item->base,
12261 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012262 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012263 xmlSchemaPResCompAttrErr(ctxt,
12264 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012265 NULL, item, item->node,
12266 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012267 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012268 } else if (base->contentType ==
12269 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012270 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012271 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012272 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012273 }
12274 /*
12275 * The type definition ·resolved· to by the ·actual
12276 * value· of the base [attribute]
12277 */
12278 ctxt->ctxtType->baseType = base;
12279 /*
12280 * TODO: This one is still needed for computation of
12281 * the content model by xmlSchemaBuildAContentModel.
12282 * Try to get rid of it.
12283 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012284 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012285 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012286 if ((item->subtypes != NULL) &&
12287 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12288 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012289
12290 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012291 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012292 /* 1.1.1 */
12293 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012294 else if ((item->subtypes->subtypes == NULL) &&
12295 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012296 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012297 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012298 XML_SCHEMA_TYPE_SEQUENCE)))
12299 /* 1.1.2 */
12300 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012301 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012302 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012303 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012304 /* 1.1.3 */
12305 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12306 if (base != NULL) {
12307 /* It will be reported later, if the base is missing. */
12308 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12309 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012310 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012311 } else if (base->contentType ==
12312 XML_SCHEMA_CONTENT_EMPTY) {
12313 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012314 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012315 XML_SCHEMA_CONTENT_ELEMENTS;
12316 } else {
12317 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012318 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012319 XML_SCHEMA_CONTENT_ELEMENTS;
12320 }
12321 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012322 break;
12323 }
12324 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012325 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012326 ctxt->ctxtType = item;
12327 /*
12328 * Start with an empty content-type type.
12329 */
12330 if (item->subtypes == NULL)
12331 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12332
12333 if ((item->subtypes == NULL) ||
12334 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012335 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012336 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012337 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12338 /*
12339 * This case is understood as shorthand for complex
12340 * content restricting the ur-type definition, and
12341 * the details of the mappings should be modified as
12342 * necessary.
12343 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012344 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12345 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012346 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012347 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012348 * Assume that we inherit the content-type type
12349 * from 'anyType', which is 'mixed' and a particle
12350 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012351 */
12352 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012353 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012354 /*
12355 * Fixup the sub components.
12356 */
12357 if ((item->subtypes != NULL) &&
12358 (item->subtypes->contentType ==
12359 XML_SCHEMA_CONTENT_UNKNOWN)) {
12360 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012361 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012362 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12363 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12364 } else if (item->subtypes != NULL) {
12365 /*
12366 * Use the content-type type of the model groups
12367 * defined, if 'mixed' is not set. If 'mixed' is set
12368 * it will expand the content-type by allowing character
12369 * content to appear.
12370 */
12371 item->contentType =
12372 item->subtypes->contentType;
12373 }
12374 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012375 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012376 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012377 break;
12378 }
12379 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012380 if (item->subtypes == NULL) {
12381 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12382 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12383 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012384 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012385 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012386 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12387 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012388 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012389 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012390 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012391 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012392 if (item->subtypes != NULL)
12393 item->contentType =
12394 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012395 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012396 /*
12397 * Removed due to implementation of the build of attribute uses.
12398 */
12399 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012400 if (item->attributes == NULL)
12401 item->attributes =
12402 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012403 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012404 }
12405 break;
12406 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012407 case XML_SCHEMA_TYPE_SIMPLE:
12408 /*
12409 * Simple Type Definition Schema Component
12410 *
12411 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012412 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012413 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12414 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012415 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 ctxt->ctxtType = item;
12417 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012418 }
12419 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012420 if ((item->baseType != NULL) &&
12421 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012422 XML_SCHEMA_CONTENT_UNKNOWN)) {
12423 /* OPTIMIZE: Actually this one will never by hit, since
12424 * the base type is already type-fixed in <restriction>.
12425 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012426 ctxt->ctxtType = item;
12427 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012428 }
12429 /* Base type:
12430 * 2 If the <list> or <union> alternative is chosen,
12431 * then the ·simple ur-type definition·.
12432 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012433 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012434 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012435 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12436 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12437 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012438 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012439 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12440 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12441 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012442 XML_SCHEMA_TYPE_RESTRICTION) {
12443 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12444
12445 /*
12446 * Variety
12447 * If the <restriction> alternative is chosen, then the
12448 * {variety} of the {base type definition}.
12449 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012450 if (item->baseType != NULL) {
12451 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012452 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012453 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12454 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012455 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012456 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12457 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012458 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012459 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012460 /*
12461 * Schema Component Constraint: Simple Type Restriction
12462 * (Facets)
12463 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12464 * applied beforehand.
12465 *
12466 * 3 The {facets} of R are the union of S and the {facets}
12467 * of B, eliminating duplicates. To eliminate duplicates,
12468 * when a facet of the same kind occurs in both S and the
12469 * {facets} of B, the one in the {facets} of B is not
12470 * included, with the exception of enumeration and pattern
12471 * facets, for which multiple occurrences with distinct values
12472 * are allowed.
12473 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012474 if (item->baseType->facetSet != NULL) {
12475 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012476 if (last != NULL)
12477 while (last->next != NULL)
12478 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012479 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012480 for (; cur != NULL; cur = cur->next) {
12481 /*
12482 * Base patterns won't be add here:
12483 * they are ORed in a type and
12484 * ANDed in derived types. This will
12485 * happed at validation level by
12486 * walking the base axis of the type.
12487 */
12488 if (cur->facet->type ==
12489 XML_SCHEMA_FACET_PATTERN)
12490 continue;
12491 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012492 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012493 (cur->facet->type !=
12494 XML_SCHEMA_FACET_PATTERN) &&
12495 (cur->facet->type !=
12496 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012497 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012498 do {
12499 if (cur->facet->type ==
12500 facet->facet->type)
12501 break;
12502 facet = facet->next;
12503 } while (facet != NULL);
12504 }
12505 if (facet == NULL) {
12506 facet = (xmlSchemaFacetLinkPtr)
12507 xmlMalloc(sizeof(xmlSchemaFacetLink));
12508 if (facet == NULL) {
12509 xmlSchemaPErrMemory(ctxt,
12510 "fixing simpleType", NULL);
12511 return;
12512 }
12513 facet->facet = cur->facet;
12514 facet->next = NULL;
12515 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012516 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012517 else
12518 last->next = facet;
12519 last = facet;
12520 }
12521 }
12522 }
12523 }
12524 }
12525 /*
12526 * Check constraints.
12527 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012528 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012529 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012530 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012531 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012532 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012533 case XML_SCHEMA_TYPE_ALL:
12534 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012535 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012536 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012537 case XML_SCHEMA_TYPE_GROUP:
12538 /*
12539 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12540 */
12541 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012542 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012543 xmlSchemaParseListRefFixup(item, ctxt);
12544 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012545 break;
12546 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012547 xmlSchemaParseUnionRefCheck(item, ctxt);
12548 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012549 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012550 case XML_SCHEMA_TYPE_BASIC:
12551 case XML_SCHEMA_TYPE_ANY:
12552 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012553 case XML_SCHEMA_TYPE_UR:
12554 case XML_SCHEMA_TYPE_ELEMENT:
12555 case XML_SCHEMA_TYPE_ATTRIBUTE:
12556 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012557 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012558 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012559 case XML_SCHEMA_FACET_MININCLUSIVE:
12560 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12561 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12562 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12563 case XML_SCHEMA_FACET_TOTALDIGITS:
12564 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12565 case XML_SCHEMA_FACET_PATTERN:
12566 case XML_SCHEMA_FACET_ENUMERATION:
12567 case XML_SCHEMA_FACET_WHITESPACE:
12568 case XML_SCHEMA_FACET_LENGTH:
12569 case XML_SCHEMA_FACET_MAXLENGTH:
12570 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012571 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12572 if (item->subtypes != NULL)
12573 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012574 break;
12575 }
12576 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012577#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012578 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012579 xmlGenericError(xmlGenericErrorContext,
12580 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012581 item->node->doc->URL,
12582 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012583 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012584 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012585 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012586 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012587 case XML_SCHEMA_CONTENT_SIMPLE:
12588 xmlGenericError(xmlGenericErrorContext, "simple\n");
12589 break;
12590 case XML_SCHEMA_CONTENT_ELEMENTS:
12591 xmlGenericError(xmlGenericErrorContext, "elements\n");
12592 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012593 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012594 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12595 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012596 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012597 xmlGenericError(xmlGenericErrorContext, "empty\n");
12598 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012599 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012600 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12601 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012602 /* Removed, since not used. */
12603 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012604 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012605 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12606 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012607 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012608 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012609 xmlGenericError(xmlGenericErrorContext, "basic\n");
12610 break;
12611 default:
12612 xmlGenericError(xmlGenericErrorContext,
12613 "not registered !!!\n");
12614 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012615 }
12616#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012617}
12618
12619/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012620 * xmlSchemaCheckFacet:
12621 * @facet: the facet
12622 * @typeDecl: the schema type definition
12623 * @ctxt: the schema parser context or NULL
12624 * @name: name of the type
12625 *
12626 * Checks the default values types, especially for facets
12627 *
12628 * Returns 0 if okay or -1 in cae of error
12629 */
12630int
12631xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012632 xmlSchemaTypePtr typeDecl,
12633 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012634{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012635 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012636 int ret = 0, reuseValCtxt = 0;
12637
Daniel Veillardce682bc2004-11-05 17:22:25 +000012638 if ((facet == NULL) || (typeDecl == NULL))
12639 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012640 /*
12641 * TODO: will the parser context be given if used from
12642 * the relaxNG module?
12643 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012644
12645 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012646 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012647 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012648 }
12649 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012650 case XML_SCHEMA_FACET_MININCLUSIVE:
12651 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12652 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012653 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12654 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012655 /*
12656 * Okay we need to validate the value
12657 * at that point.
12658 */
12659 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012660 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012661
12662 /* 4.3.5.5 Constraints on enumeration Schema Components
12663 * Schema Component Constraint: enumeration valid restriction
12664 * It is an ·error· if any member of {value} is not in the
12665 * ·value space· of {base type definition}.
12666 *
12667 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12668 * The value ·must· be in the
12669 * ·value space· of the ·base type·.
12670 */
12671 /*
12672 * This function is intended to deliver a compiled value
12673 * on the facet. In XML Schemas the type holding a facet,
12674 * cannot be a built-in type. Thus to ensure that other API
12675 * calls (relaxng) do work, if the given type is a built-in
12676 * type, we will assume that the given built-in type *is
12677 * already* the base type.
12678 */
12679 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12680 base = typeDecl->baseType;
12681 if (base == NULL) {
12682 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012683 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012684 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012685 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012686 typeDecl->name, NULL);
12687 return (-1);
12688 }
12689 } else
12690 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012691 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012692 * This avoids perseverative creation of the
12693 * validation context if a parser context is
12694 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012695 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012696 if (ctxt != NULL) {
12697 reuseValCtxt = 1;
12698 if (ctxt->vctxt == NULL) {
12699 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12700 return (-1);
12701 }
12702 vctxt = ctxt->vctxt;
12703 } else {
12704 vctxt = xmlSchemaNewValidCtxt(NULL);
12705 if (vctxt == NULL) {
12706 xmlSchemaPErr(ctxt, typeDecl->node,
12707 XML_SCHEMAP_INTERNAL,
12708 "Internal error: xmlSchemaCheckFacet, "
12709 "creating a new validation context.\n",
12710 NULL, NULL);
12711 return (-1);
12712 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012713 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012715 vctxt->node = facet->node;
12716 vctxt->cur = NULL;
12717 /*
12718 * NOTE: This call does not check the content nodes,
12719 * since they are not available:
12720 * facet->node is just the node holding the facet
12721 * definition, *not* the attribute holding the *value*
12722 * of the facet.
12723 */
12724 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12725 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012726 facet->val = vctxt->value;
12727 vctxt->value = NULL;
12728 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012729 /* error code */
12730 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012731 xmlSchemaPErrExt(ctxt, facet->node,
12732 XML_SCHEMAP_INVALID_FACET,
12733 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012734 "Type definition '%s': The value '%s' of the "
12735 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012736 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012737 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012738 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012739 }
12740 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012741 } else if (ret < 0) {
12742 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012743 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012744 NULL, NULL, NULL,
12745 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012746 "failed to validate the value '%s' name of the "
12747 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012748 facet->value,
12749 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12750 base->name, NULL, NULL);
12751 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012752 }
12753 if (reuseValCtxt == 0)
12754 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012755 break;
12756 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012757 case XML_SCHEMA_FACET_PATTERN:
12758 facet->regexp = xmlRegexpCompile(facet->value);
12759 if (facet->regexp == NULL) {
12760 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012761 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012762 "Type definition '%s': The value '%s' of the "
12763 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012764 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012765 ret = -1;
12766 }
12767 break;
12768 case XML_SCHEMA_FACET_TOTALDIGITS:
12769 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12770 case XML_SCHEMA_FACET_LENGTH:
12771 case XML_SCHEMA_FACET_MAXLENGTH:
12772 case XML_SCHEMA_FACET_MINLENGTH:{
12773 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012774
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012775 tmp =
12776 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12777 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012778 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012779 if (tmp != 0) {
12780 /* error code */
12781 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012782 xmlSchemaPErrExt(ctxt, facet->node,
12783 XML_SCHEMAP_INVALID_FACET_VALUE,
12784 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012785 "Type definition '%s': The value '%s' of the "
12786 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012787 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012788 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012789 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012790 }
12791 ret = -1;
12792 }
12793 break;
12794 }
12795 case XML_SCHEMA_FACET_WHITESPACE:{
12796 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12797 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12798 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12799 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12800 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12801 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12802 } else {
12803 if (ctxt != NULL) {
12804 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012805 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012806 "Type definition '%s': The value '%s' of the "
12807 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012808 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012809 }
12810 ret = -1;
12811 }
12812 }
12813 default:
12814 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012815 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012816 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012817}
12818
12819/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012820 * xmlSchemaCheckDefaults:
12821 * @typeDecl: the schema type definition
12822 * @ctxt: the schema parser context
12823 *
12824 * Checks the default values types, especially for facets
12825 */
12826static void
12827xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012828 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012829{
Daniel Veillard4255d502002-04-16 15:50:10 +000012830 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012831 name = typeDecl->name;
12832 /*
12833 * NOTE: It is intended to use the facets list, instead
12834 * of facetSet.
12835 */
12836 if (typeDecl->facets != NULL) {
12837 xmlSchemaFacetPtr facet = typeDecl->facets;
12838
12839 while (facet != NULL) {
12840 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12841 facet = facet->next;
12842 }
12843 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012844}
12845
12846/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012847 * xmlSchemaGetCircModelGrDefRef:
12848 * @ctxtGr: the searched model group
12849 * @list: the list of model groups to be processed
12850 *
12851 * This one is intended to be used by
12852 * xmlSchemaCheckGroupDefCircular only.
12853 *
12854 * Returns the circular model group definition reference, otherwise NULL.
12855 */
12856static xmlSchemaTypePtr
12857xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12858 xmlSchemaTypePtr gr)
12859{
12860 xmlSchemaTypePtr circ = NULL;
12861 int marked;
12862 /*
12863 * We will search for an model group reference which
12864 * references the context model group definition.
12865 */
12866 while (gr != NULL) {
12867 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
12868 (gr->type == XML_SCHEMA_TYPE_ALL) ||
12869 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
12870 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
12871 (gr->subtypes != NULL)) {
12872 marked = 0;
12873 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
12874 (gr->ref != NULL)) {
12875 if (gr->subtypes == ctxtGrDef)
12876 return (gr);
12877 else if (gr->subtypes->flags &
12878 XML_SCHEMAS_TYPE_MARKED) {
12879 gr = gr->next;
12880 continue;
12881 } else {
12882 /*
12883 * Mark to avoid infinite recursion on
12884 * circular references not yet examined.
12885 */
12886 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
12887 marked = 1;
12888 }
12889 if (gr->subtypes->subtypes != NULL)
12890 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12891 gr->subtypes->subtypes);
12892 /*
12893 * Unmark the visited model group definition.
12894 */
12895 if (marked)
12896 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
12897 if (circ != NULL)
12898 return (circ);
12899 } else {
12900 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12901 (xmlSchemaTypePtr) gr->subtypes);
12902 if (circ != NULL)
12903 return (circ);
12904 }
12905
12906 }
12907 gr = gr->next;
12908 }
12909 return (NULL);
12910}
12911
12912/**
12913 * xmlSchemaCheckGroupDefCircular:
12914 * attrGr: the model group definition
12915 * @ctxt: the parser context
12916 * @name: the name
12917 *
12918 * Checks for circular references to model group definitions.
12919 */
12920static void
12921xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
12922 xmlSchemaParserCtxtPtr ctxt,
12923 const xmlChar * name ATTRIBUTE_UNUSED)
12924{
12925 /*
12926 * Schema Component Constraint: Model Group Correct
12927 * 2 Circular groups are disallowed. That is, within the {particles}
12928 * of a group there must not be at any depth a particle whose {term}
12929 * is the group itself.
12930 */
12931 /*
12932 * NOTE: "gr->subtypes" holds the referenced group.
12933 */
12934 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
12935 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
12936 (modelGrDef->subtypes == NULL))
12937 return;
12938 else {
12939 xmlSchemaTypePtr circ;
12940
12941 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
12942 if (circ != NULL) {
12943 /*
12944 * TODO: Report the referenced attr group as QName.
12945 */
12946 xmlSchemaPCustomErr(ctxt,
12947 XML_SCHEMAP_MG_PROPS_CORRECT_2,
12948 NULL, NULL, circ->node,
12949 "Circular reference to the model group definition '%s' "
12950 "defined", modelGrDef->name);
12951 /*
12952 * NOTE: We will cut the reference to avoid further
12953 * confusion of the processor.
12954 * TODO: SPEC: Does the spec define how to process here?
12955 */
12956 circ->subtypes = NULL;
12957 }
12958 }
12959}
12960
12961
12962/**
12963 * xmlSchemaGetCircAttrGrRef:
12964 * @ctxtGr: the searched attribute group
12965 * @attr: the current attribute list to be processed
12966 *
12967 * This one is intended to be used by
12968 * xmlSchemaCheckSRCAttributeGroupCircular only.
12969 *
12970 * Returns the circular attribute grou reference, otherwise NULL.
12971 */
12972static xmlSchemaAttributeGroupPtr
12973xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
12974 xmlSchemaAttributePtr attr)
12975{
12976 xmlSchemaAttributeGroupPtr circ = NULL, gr;
12977 int marked;
12978 /*
12979 * We will search for an attribute group reference which
12980 * references the context attribute group.
12981 */
12982 while (attr != NULL) {
12983 marked = 0;
12984 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12985 gr = (xmlSchemaAttributeGroupPtr) attr;
12986 if (gr->refItem != NULL) {
12987 if (gr->refItem == ctxtGr)
12988 return (gr);
12989 else if (gr->refItem->flags &
12990 XML_SCHEMAS_ATTRGROUP_MARKED) {
12991 attr = attr->next;
12992 continue;
12993 } else {
12994 /*
12995 * Mark as visited to avoid infinite recursion on
12996 * circular references not yet examined.
12997 */
12998 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
12999 marked = 1;
13000 }
13001 }
13002 if (gr->attributes != NULL)
13003 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
13004 /*
13005 * Unmark the visited group's attributes.
13006 */
13007 if (marked)
13008 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
13009 if (circ != NULL)
13010 return (circ);
13011 }
13012 attr = attr->next;
13013 }
13014 return (NULL);
13015}
13016
13017/**
13018 * xmlSchemaCheckSRCAttributeGroupCircular:
13019 * attrGr: the attribute group definition
13020 * @ctxt: the parser context
13021 * @name: the name
13022 *
13023 * Checks for circular references of attribute groups.
13024 */
13025static void
13026xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
13027 xmlSchemaParserCtxtPtr ctxt,
13028 const xmlChar * name ATTRIBUTE_UNUSED)
13029{
13030 /*
13031 * Schema Representation Constraint:
13032 * Attribute Group Definition Representation OK
13033 * 3 Circular group reference is disallowed outside <redefine>.
13034 * That is, unless this element information item's parent is
13035 * <redefine>, then among the [children], if any, there must
13036 * not be an <attributeGroup> with ref [attribute] which resolves
13037 * to the component corresponding to this <attributeGroup>. Indirect
13038 * circularity is also ruled out. That is, when QName resolution
13039 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13040 * any <attributeGroup>s with a ref [attribute] among the [children],
13041 * it must not be the case that a ·QName· is encountered at any depth
13042 * which resolves to the component corresponding to this <attributeGroup>.
13043 */
13044 /*
13045 * Only global components can be referenced.
13046 */
13047 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
13048 (attrGr->attributes == NULL))
13049 return;
13050 else {
13051 xmlSchemaAttributeGroupPtr circ;
13052
13053 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
13054 if (circ != NULL) {
13055 /*
13056 * TODO: Report the referenced attr group as QName.
13057 */
13058 xmlSchemaPCustomErr(ctxt,
13059 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13060 NULL, NULL, circ->node,
13061 "Circular reference to the attribute group '%s' "
13062 "defined", attrGr->name);
13063 /*
13064 * NOTE: We will cut the reference to avoid further
13065 * confusion of the processor.
13066 * BADSPEC: The spec should define how to process in this case.
13067 */
13068 circ->attributes = NULL;
13069 circ->refItem = NULL;
13070 }
13071 }
13072}
13073
13074/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013075 * xmlSchemaAttrGrpFixup:
13076 * @attrgrpDecl: the schema attribute definition
13077 * @ctxt: the schema parser context
13078 * @name: the attribute name
13079 *
13080 * Fixes finish doing the computations on the attributes definitions
13081 */
13082static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013083xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013084 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013085{
13086 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013087 name = attrgrp->name;
13088 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013089 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013090 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013091 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013092
Daniel Veillardc0826a72004-08-10 14:17:33 +000013093 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13094 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013095 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013096 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013097 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013098 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13099 "ref", attrgrp->ref, attrgrp->refNs,
13100 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013101 return;
13102 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013103 attrgrp->refItem = ref;
13104 /*
13105 * Check for self reference!
13106 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013107 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013108 attrgrp->attributes = ref->attributes;
13109 attrgrp->attributeWildcard = ref->attributeWildcard;
13110 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013111}
13112
13113/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013114 * xmlSchemaAttrCheckValConstr:
13115 * @item: an schema attribute declaration/use
13116 * @ctxt: a schema parser context
13117 * @name: the name of the attribute
13118 *
13119 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013120 *
13121 * Fixes finish doing the computations on the attributes definitions
13122 */
13123static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013124xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13125 xmlSchemaParserCtxtPtr ctxt,
13126 const xmlChar * name ATTRIBUTE_UNUSED)
13127{
13128
13129 /*
13130 * a-props-correct
13131 * Schema Component Constraint: Attribute Declaration Properties Correct
13132 *
13133 * 2 if there is a {value constraint}, the canonical lexical
13134 * representation of its value must be ·valid· with respect
13135 * to the {type definition} as defined in String Valid (§3.14.4).
13136 */
13137
13138 if (item->defValue != NULL) {
13139 int ret;
13140 xmlNodePtr node;
13141 xmlSchemaTypePtr type;
13142
13143 if (item->subtypes == NULL) {
13144 xmlSchemaPErr(ctxt, item->node,
13145 XML_SCHEMAP_INTERNAL,
13146 "Internal error: xmlSchemaCheckAttrValConstr, "
13147 "type is missing... skipping validation of "
13148 "value constraint", NULL, NULL);
13149 return;
13150 }
13151
13152 /*
13153 * TODO: Try to avoid creating a new context.
13154 * TODO: This all is not very performant.
13155 */
13156 type = item->subtypes;
13157 /*
13158 * Ensure there's validation context.
13159 */
13160 if (ctxt->vctxt == NULL) {
13161 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13162 xmlSchemaPErr(ctxt, item->node,
13163 XML_SCHEMAP_INTERNAL,
13164 "Internal error: xmlSchemaCheckAttrValConstr, "
13165 "creating a new validation context.\n",
13166 NULL, NULL);
13167 return;
13168 }
13169 }
13170
13171 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13172 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13173 else
13174 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13175 ctxt->vctxt->node = node;
13176 ctxt->vctxt->cur = NULL;
13177 /*
13178 * NOTE: This call does not check the content nodes,
13179 * since they are not available:
13180 * facet->node is just the node holding the facet
13181 * definition, *not* the attribute holding the *value*
13182 * of the facet.
13183 */
13184 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13185 item->defValue, 0, 1, 1, 0);
13186 if (ret == 0) {
13187 /*
13188 * Store the computed value.
13189 */
13190 item->defVal = ctxt->vctxt->value;
13191 ctxt->vctxt->value = NULL;
13192 } else if (ret > 0) {
13193 if (ctxt != NULL) {
13194 xmlSchemaPSimpleTypeErr(ctxt,
13195 XML_SCHEMAP_A_PROPS_CORRECT_2,
13196 NULL, NULL, node,
13197 type, NULL, item->defValue,
13198 NULL, NULL, NULL);
13199 }
13200 } else if (ret < 0) {
13201 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13202 NULL, NULL, node,
13203 "Internal error: xmlSchemaAttrCheckValConstr, "
13204 "failed to validate the value constraint of the "
13205 "attribute decl/use against the type '%s'",
13206 type->name);
13207 }
13208 }
13209}
13210
13211#if 0 /* Not used yet. */
13212static int
13213xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13214 xmlSchemaElementPtr edecl)
13215{
13216 /*
13217 * TODO: 1 The values of the properties of an element declaration must be as
13218 * described in the property tableau in The Element Declaration Schema
13219 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13220 */
13221 /*
13222 * 2 If there is a {value constraint}, the canonical lexical
13223 * representation of its value must be ·valid· with respect to the {type
13224 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13225 *
13226 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13227 */
13228 /*
13229 * 3 If there is a non-·absent· {substitution group affiliation},
13230 * then {scope} must be global.
13231 *
13232 * NOTE: This is done in xmlSchemaParseElement.
13233 * TODO: Move it to this layer here.
13234 */
13235 /*
13236 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13237 * of the element declaration must be validly derived from the {type
13238 * definition} of the {substitution group affiliation}, given the value
13239 * of the {substitution group exclusions} of the {substitution group
13240 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13241 * (if the {type definition} is complex) or as defined in
13242 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13243 * simple).
13244 */
13245 /*
13246 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13247 * is or is derived from ID then there must not be a {value constraint}.
13248 * Note: The use of ID as a type definition for elements goes beyond
13249 * XML 1.0, and should be avoided if backwards compatibility is desired
13250 */
13251 /*
13252 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13253 * be possible to return to an element declaration by repeatedly following
13254 * the {substitution group affiliation} property.
13255 */
13256}
13257#endif
13258
13259/**
13260 * xmlSchemaCheckElemValConstr:
13261 * @item: an schema element declaration/particle
13262 * @ctxt: a schema parser context
13263 * @name: the name of the attribute
13264 *
13265 * Validates the value constraints of an element declaration.
13266 *
13267 * Fixes finish doing the computations on the element declarations.
13268 */
13269static void
13270xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13271 xmlSchemaParserCtxtPtr ctxt,
13272 const xmlChar * name ATTRIBUTE_UNUSED)
13273{
13274 if (decl->value != NULL) {
13275 int ret;
13276 xmlNodePtr node = NULL;
13277 xmlSchemaTypePtr type;
13278
13279 /*
13280 * 2 If there is a {value constraint}, the canonical lexical
13281 * representation of its value must be ·valid· with respect to the {type
13282 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13283 */
13284 if (decl->subtypes == NULL) {
13285 xmlSchemaPErr(ctxt, decl->node,
13286 XML_SCHEMAP_INTERNAL,
13287 "Internal error: xmlSchemaCheckElemValConstr, "
13288 "type is missing... skipping validation of "
13289 "the value constraint", NULL, NULL);
13290 return;
13291 }
13292 /*
13293 * Ensure there's a validation context.
13294 */
13295 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13296 return;
13297
13298 type = decl->subtypes;
13299
13300 if (decl->node != NULL) {
13301 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13302 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13303 else
13304 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13305 }
13306 ctxt->vctxt->node = node;
13307 ctxt->vctxt->cur = NULL;
13308 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13309 node);
13310 if (ret == 0) {
13311 /*
13312 * Consume the computed value.
13313 */
13314 decl->defVal = ctxt->vctxt->value;
13315 ctxt->vctxt->value = NULL;
13316 } else if (ret < 0) {
13317 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13318 NULL, NULL, node,
13319 "Internal error: xmlSchemaElemCheckValConstr, "
13320 "failed to validate the value constraint of the "
13321 "element declaration '%s'",
13322 decl->name);
13323 }
13324 }
13325}
13326
13327/**
13328 * xmlSchemaAttrFixup:
13329 * @item: an schema attribute declaration/use.
13330 * @ctxt: a schema parser context
13331 * @name: the name of the attribute
13332 *
13333 * Fixes finish doing the computations on attribute declarations/uses.
13334 */
13335static void
13336xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13337 xmlSchemaParserCtxtPtr ctxt,
13338 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013339{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013340 /*
13341 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013342 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013343 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013344 /*
13345 * The simple type definition corresponding to the <simpleType> element
13346 * information item in the [children], if present, otherwise the simple
13347 * type definition ·resolved· to by the ·actual value· of the type
13348 * [attribute], if present, otherwise the ·simple ur-type definition·.
13349 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013350 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013351 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013352 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13353 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013354 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013355 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013356 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013357
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013358 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13359 item->typeNs);
13360 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013361 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013362 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013363 NULL, (xmlSchemaTypePtr) item, item->node,
13364 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013365 XML_SCHEMA_TYPE_SIMPLE, NULL);
13366 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013367 item->subtypes = type;
13368
13369 } else if (item->ref != NULL) {
13370 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013371
Daniel Veillardc0826a72004-08-10 14:17:33 +000013372 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013373 * We have an attribute use here; assign the referenced
13374 * attribute declaration.
13375 */
13376 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013377 * TODO: Evaluate, what errors could occur if the declaration is not
13378 * found. It might be possible that the "typefixup" might crash if
13379 * no ref declaration was found.
13380 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013381 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13382 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013383 xmlSchemaPResCompAttrErr(ctxt,
13384 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013385 NULL, (xmlSchemaTypePtr) item, item->node,
13386 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013387 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013388 return;
13389 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013390 item->refDecl = decl;
13391 xmlSchemaAttrFixup(decl, ctxt, NULL);
13392
13393 item->subtypes = decl->subtypes;
13394 /*
13395 * Attribute Use Correct
13396 * au-props-correct.2: If the {attribute declaration} has a fixed
13397 * {value constraint}, then if the attribute use itself has a
13398 * {value constraint}, it must also be fixed and its value must match
13399 * that of the {attribute declaration}'s {value constraint}.
13400 */
13401 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13402 (item->defValue != NULL)) {
13403 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13404 (!xmlStrEqual(item->defValue, decl->defValue))) {
13405 xmlSchemaPCustomErr(ctxt,
13406 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13407 NULL, NULL, item->node,
13408 "The value constraint must be fixed "
13409 "and match the referenced attribute "
13410 "declarations's value constraint '%s'",
13411 decl->defValue);
13412 }
13413 /*
13414 * FUTURE: One should change the values of the attr. use
13415 * if ever validation should be attempted even if the
13416 * schema itself was not fully valid.
13417 */
13418 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013419 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013420 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13421 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013422}
13423
13424/**
13425 * xmlSchemaParse:
13426 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013427 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013428 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013429 * XML Shema struture which can be used to validate instances.
13430 * *WARNING* this interface is highly subject to change
13431 *
13432 * Returns the internal XML Schema structure built from the resource or
13433 * NULL in case of error
13434 */
13435xmlSchemaPtr
13436xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13437{
13438 xmlSchemaPtr ret = NULL;
13439 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013440 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013441 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013442
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013443 /*
13444 * This one is used if the schema to be parsed was specified via
13445 * the API; i.e. not automatically by the validated instance document.
13446 */
13447
Daniel Veillard4255d502002-04-16 15:50:10 +000013448 xmlSchemaInitTypes();
13449
Daniel Veillard6045c902002-10-09 21:13:59 +000013450 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013451 return (NULL);
13452
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013453 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013454 ctxt->counter = 0;
13455 ctxt->container = NULL;
13456
13457 /*
13458 * First step is to parse the input document into an DOM/Infoset
13459 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013460 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013461 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13462 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013463 if (doc == NULL) {
13464 xmlSchemaPErr(ctxt, NULL,
13465 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013466 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013467 ctxt->URL, NULL);
13468 return (NULL);
13469 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013470 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013471 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13472 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013473 if (doc == NULL) {
13474 xmlSchemaPErr(ctxt, NULL,
13475 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013476 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013477 NULL, NULL);
13478 return (NULL);
13479 }
13480 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013481 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013482 } else if (ctxt->doc != NULL) {
13483 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013484 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013485 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013486 xmlSchemaPErr(ctxt, NULL,
13487 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013488 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013489 NULL, NULL);
13490 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013491 }
13492
13493 /*
13494 * Then extract the root and Schema parse it
13495 */
13496 root = xmlDocGetRootElement(doc);
13497 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013498 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13499 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013500 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013501 if (!preserve) {
13502 xmlFreeDoc(doc);
13503 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013504 return (NULL);
13505 }
13506
13507 /*
13508 * Remove all the blank text nodes
13509 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013510 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013511
13512 /*
13513 * Then do the parsing for good
13514 */
13515 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013516 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013517 if (!preserve) {
13518 xmlFreeDoc(doc);
13519 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013520 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013521 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013522 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013523 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013524 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013525 ctxt->ctxtType = NULL;
13526 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013527 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013528 * Then fixup all attributes declarations
13529 */
13530 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13531
13532 /*
13533 * Then fixup all attributes group declarations
13534 */
13535 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13536 ctxt);
13537
13538 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013539 * Check attribute groups for circular references.
13540 */
13541 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13542 xmlSchemaCheckAttributeGroupCircular, ctxt);
13543
13544 /*
13545 * Then fixup all model group definitions.
13546 */
13547 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013548
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013549 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013550 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013551 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013552 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013553
13554 /*
13555 * Then fix references of element declaration; apply constraints.
13556 */
13557 xmlHashScanFull(ret->elemDecl,
13558 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013559
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013560 /*
13561 * Check model groups defnitions for circular references.
13562 */
13563 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13564 xmlSchemaCheckGroupDefCircular, ctxt);
13565
Daniel Veillard4255d502002-04-16 15:50:10 +000013566 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013567 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013568 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013569 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013570 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013571
13572 /*
13573 * Then check the defaults part of the type like facets values
13574 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013575 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000013576
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013577 /*
13578 * Validate the value constraint of attribute declarations/uses.
13579 */
13580 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13581
13582 /*
13583 * Validate the value constraint of element declarations.
13584 */
13585 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13586
Daniel Veillardc0826a72004-08-10 14:17:33 +000013587
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013588 if (ctxt->nberrors != 0) {
13589 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013590 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013591 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013592 return (ret);
13593}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013594
Daniel Veillard4255d502002-04-16 15:50:10 +000013595/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013596 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013597 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013598 * @err: the error callback
13599 * @warn: the warning callback
13600 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013601 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013602 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013603 */
13604void
13605xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013606 xmlSchemaValidityErrorFunc err,
13607 xmlSchemaValidityWarningFunc warn, void *ctx)
13608{
Daniel Veillard4255d502002-04-16 15:50:10 +000013609 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013610 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013611 ctxt->error = err;
13612 ctxt->warning = warn;
13613 ctxt->userData = ctx;
13614}
13615
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013616/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013617 * xmlSchemaGetParserErrors:
13618 * @ctxt: a XMl-Schema parser context
13619 * @err: the error callback result
13620 * @warn: the warning callback result
13621 * @ctx: contextual data for the callbacks result
13622 *
13623 * Get the callback information used to handle errors for a parser context
13624 *
13625 * Returns -1 in case of failure, 0 otherwise
13626 */
13627int
13628xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13629 xmlSchemaValidityErrorFunc * err,
13630 xmlSchemaValidityWarningFunc * warn, void **ctx)
13631{
13632 if (ctxt == NULL)
13633 return(-1);
13634 if (err != NULL)
13635 *err = ctxt->error;
13636 if (warn != NULL)
13637 *warn = ctxt->warning;
13638 if (ctx != NULL)
13639 *ctx = ctxt->userData;
13640 return(0);
13641}
13642
13643/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013644 * xmlSchemaFacetTypeToString:
13645 * @type: the facet type
13646 *
13647 * Convert the xmlSchemaTypeType to a char string.
13648 *
13649 * Returns the char string representation of the facet type if the
13650 * type is a facet and an "Internal Error" string otherwise.
13651 */
13652static const char *
13653xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13654{
13655 switch (type) {
13656 case XML_SCHEMA_FACET_PATTERN:
13657 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013658 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013659 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013660 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013661 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013662 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013663 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013664 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013665 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013666 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013667 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013668 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013669 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013670 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013671 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013672 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013673 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013674 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013675 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013676 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013677 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013678 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013679 return ("fractionDigits");
13680 default:
13681 break;
13682 }
13683 return ("Internal Error");
13684}
13685
Daniel Veillardc0826a72004-08-10 14:17:33 +000013686
Daniel Veillardc0826a72004-08-10 14:17:33 +000013687
13688static int
13689xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13690{
13691 xmlSchemaTypePtr anc;
13692
13693 /*
13694 * The normalization type can be changed only for types which are derived
13695 * from xsd:string.
13696 */
13697 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013698 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013699 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013700 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
13701 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013702 else {
13703 /*
13704 * For all ·atomic· datatypes other than string (and types ·derived·
13705 * by ·restriction· from it) the value of whiteSpace is fixed to
13706 * collapse
13707 */
13708 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13709 }
13710 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13711 /*
13712 * For list types the facet "whiteSpace" is fixed to "collapse".
13713 */
13714 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13715 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13716 return (-1);
13717 } else if (type->facetSet != NULL) {
13718 xmlSchemaTypePtr anyST;
13719 xmlSchemaFacetLinkPtr lin;
13720
13721 /*
13722 * Atomic types.
13723 */
13724 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13725 anc = type->baseType;
13726 do {
13727 /*
13728 * For all ·atomic· datatypes other than string (and types ·derived·
13729 * by ·restriction· from it) the value of whiteSpace is fixed to
13730 * collapse
13731 */
13732 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13733 (anc->builtInType == XML_SCHEMAS_STRING)) {
13734
13735 lin = type->facetSet;
13736 do {
13737 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13738 if (lin->facet->whitespace ==
13739 XML_SCHEMAS_FACET_COLLAPSE) {
13740 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13741 } else if (lin->facet->whitespace ==
13742 XML_SCHEMAS_FACET_REPLACE) {
13743 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13744 } else
13745 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13746 break;
13747 }
13748 lin = lin->next;
13749 } while (lin != NULL);
13750 break;
13751 }
13752 anc = anc->baseType;
13753 } while (anc != anyST);
13754 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13755 }
13756 return (-1);
13757}
13758
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013759/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013760 * xmlSchemaValidateFacetsInternal:
13761 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013762 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013763 * @facets: the list of facets to check
13764 * @value: the lexical repr of the value to validate
13765 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013766 * @fireErrors: if 0, only internal errors will be fired;
13767 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013768 *
13769 * Check a value against all facet conditions
13770 *
13771 * Returns 0 if the element is schemas valid, a positive error code
13772 * number otherwise and -1 in case of internal or API error.
13773 */
13774static int
13775xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013776 xmlSchemaTypePtr type,
13777 const xmlChar * value,
13778 unsigned long length,
13779 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013780{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013781 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013782 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013783 xmlSchemaTypePtr biType; /* The build-in type. */
13784 xmlSchemaTypePtr tmpType;
13785 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013786 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013787 xmlSchemaFacetPtr facet;
13788 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013789
Daniel Veillardc0826a72004-08-10 14:17:33 +000013790#ifdef DEBUG_UNION_VALIDATION
13791 printf("Facets of type: '%s'\n", (const char *) type->name);
13792 printf(" fireErrors: %d\n", fireErrors);
13793#endif
13794
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013795 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013796 /*
13797 * NOTE: Do not jump away, if the facetSet of the given type is
13798 * empty: until now, "pattern" facets of the *base types* need to
13799 * be checked as well.
13800 */
13801 biType = type->baseType;
13802 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13803 biType = biType->baseType;
13804 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013805 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013806 "Internal error: xmlSchemaValidateFacetsInternal, "
13807 "the base type axis of the given type '%s' does not resolve to "
13808 "a built-in type.\n",
13809 type->name, NULL);
13810 return (-1);
13811 }
13812
13813 if (type->facetSet != NULL) {
13814 facetLink = type->facetSet;
13815 while (facetLink != NULL) {
13816 facet = facetLink->facet;
13817 /*
13818 * Skip the pattern "whiteSpace": it is used to
13819 * format the character content beforehand.
13820 */
13821 switch (facet->type) {
13822 case XML_SCHEMA_FACET_WHITESPACE:
13823 case XML_SCHEMA_FACET_PATTERN:
13824 case XML_SCHEMA_FACET_ENUMERATION:
13825 break;
13826 case XML_SCHEMA_FACET_LENGTH:
13827 case XML_SCHEMA_FACET_MINLENGTH:
13828 case XML_SCHEMA_FACET_MAXLENGTH:
13829 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13830 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13831 value, length, 0);
13832 len = length;
13833 } else
13834 ret = xmlSchemaValidateLengthFacet(biType, facet,
13835 value, ctxt->value, &len);
13836 break;
13837 default:
13838 ret = xmlSchemaValidateFacet(biType, facet, value,
13839 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013840 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013841 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013842 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013843 "Internal error: xmlSchemaValidateFacetsInternal, "
13844 "validating facet of type '%s'.\n",
13845 type->name, NULL);
13846 break;
13847 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013848 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013849 type, facet, NULL, NULL, NULL, NULL);
13850 }
13851
13852 facetLink = facetLink->next;
13853 }
13854 if (ret >= 0) {
13855 /*
13856 * Process enumerations.
13857 */
13858 retFacet = 0;
13859 facetLink = type->facetSet;
13860 while (facetLink != NULL) {
13861 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
13862 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13863 value, ctxt->value);
13864 if (retFacet <= 0)
13865 break;
13866 }
13867 facetLink = facetLink->next;
13868 }
13869 if (retFacet > 0) {
13870 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
13871 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013872 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013873 value, 0, type, NULL, NULL, NULL, NULL, NULL);
13874 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013875 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013876 "Internal error: xmlSchemaValidateFacetsInternal, "
13877 "validating facet of type '%s'.\n",
13878 BAD_CAST "enumeration", NULL);
13879 ret = -1;
13880 }
13881 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013882 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013883 if (ret >= 0) {
13884 /*
13885 * Process patters. Pattern facets are ORed at type level
13886 * and ANDed if derived. Walk the base type axis.
13887 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013888 tmpType = type;
13889 facet = NULL;
13890 do {
13891 retFacet = 0;
13892 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013893 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013894 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13895 continue;
13896 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13897 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013898 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013899 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013900 else if (retFacet < 0) {
13901 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13902 "Internal error: xmlSchemaValidateFacetsInternal, "
13903 "validating 'pattern' facet '%s' of type '%s'.\n",
13904 facetLink->facet->value, tmpType->name);
13905 ret = -1;
13906 break;
13907 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013908 /* Save the last non-validating facet. */
13909 facet = facetLink->facet;
13910 }
13911 if (retFacet != 0)
13912 break;
13913 tmpType = tmpType->baseType;
13914 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013915 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013916 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13917 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013918 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013919 NULL, NULL, NULL, NULL);
13920 }
13921 }
13922 }
13923
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013924 return (ret);
13925}
13926
Daniel Veillard4255d502002-04-16 15:50:10 +000013927/************************************************************************
13928 * *
13929 * Simple type validation *
13930 * *
13931 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013932
Daniel Veillard4255d502002-04-16 15:50:10 +000013933
13934/************************************************************************
13935 * *
13936 * DOM Validation code *
13937 * *
13938 ************************************************************************/
13939
Daniel Veillard4255d502002-04-16 15:50:10 +000013940static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013941 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013942 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013943static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013944 xmlSchemaTypePtr type,
13945 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000013946
Daniel Veillard3646d642004-06-02 19:19:14 +000013947
13948/**
13949 * xmlSchemaFreeAttrStates:
13950 * @state: a list of attribute states
13951 *
13952 * Free the given list of attribute states
13953 *
13954 */
13955static void
13956xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13957{
13958 xmlSchemaAttrStatePtr tmp;
13959 while (state != NULL) {
13960 tmp = state;
13961 state = state->next;
13962 xmlFree(tmp);
13963 }
13964}
13965
Daniel Veillard4255d502002-04-16 15:50:10 +000013966/**
13967 * xmlSchemaRegisterAttributes:
13968 * @ctxt: a schema validation context
13969 * @attrs: a list of attributes
13970 *
13971 * Register the list of attributes as the set to be validated on that element
13972 *
13973 * Returns -1 in case of error, 0 otherwise
13974 */
13975static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013976xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
13977{
Daniel Veillard3646d642004-06-02 19:19:14 +000013978 xmlSchemaAttrStatePtr tmp;
13979
13980 ctxt->attr = NULL;
13981 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013982 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013983 if ((attrs->ns != NULL) &&
13984 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
13985 attrs = attrs->next;
13986 continue;
13987 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013988 tmp = (xmlSchemaAttrStatePtr)
13989 xmlMalloc(sizeof(xmlSchemaAttrState));
13990 if (tmp == NULL) {
13991 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
13992 return (-1);
13993 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013994 tmp->attr = attrs;
13995 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
13996 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013997 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013998 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013999 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000014000 else
14001 ctxt->attrTop->next = tmp;
14002 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014003 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014004 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014005 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014006}
14007
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014008#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000014009/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014010 * xmlSchemaValidateCheckNodeList
14011 * @nodelist: the list of nodes
14012 *
14013 * Check the node list is only made of text nodes and entities pointing
14014 * to text nodes
14015 *
14016 * Returns 1 if true, 0 if false and -1 in case of error
14017 */
14018static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014019xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
14020{
Daniel Veillard4255d502002-04-16 15:50:10 +000014021 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014022 if (nodelist->type == XML_ENTITY_REF_NODE) {
14023 TODO /* implement recursion in the entity content */
14024 }
14025 if ((nodelist->type != XML_TEXT_NODE) &&
14026 (nodelist->type != XML_COMMENT_NODE) &&
14027 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000014028 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014029 return (0);
14030 }
14031 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014032 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014033 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014034}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014035#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014036
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014037static void
14038xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14039{
14040 int i, nbItems;
14041 xmlSchemaTypePtr item, *items;
14042
14043
14044 /*
14045 * During the Assemble of the schema ctxt->curItems has
14046 * been filled with the relevant new items. Fix those up.
14047 */
14048 nbItems = ctxt->assemble->nbItems;
14049 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14050
14051 for (i = 0; i < nbItems; i++) {
14052 item = items[i];
14053 switch (item->type) {
14054 case XML_SCHEMA_TYPE_ATTRIBUTE:
14055 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14056 break;
14057 case XML_SCHEMA_TYPE_ELEMENT:
14058 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14059 NULL, NULL, NULL);
14060 break;
14061 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14062 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14063 ctxt, NULL);
14064 break;
14065 case XML_SCHEMA_TYPE_GROUP:
14066 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14067 default:
14068 break;
14069 }
14070 }
14071 /*
14072 * Circularity checks.
14073 */
14074 for (i = 0; i < nbItems; i++) {
14075 item = items[i];
14076 switch (item->type) {
14077 case XML_SCHEMA_TYPE_GROUP:
14078 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14079 break;
14080 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14081 xmlSchemaCheckAttributeGroupCircular(
14082 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14083 break;
14084 default:
14085 break;
14086 }
14087 }
14088 /*
14089 * Fixup for all other item.
14090 * TODO: Hmm, not sure if starting from complex/simple types,
14091 * all subsequent items will be reached.
14092 */
14093 for (i = 0; i < nbItems; i++) {
14094 item = items[i];
14095 switch (item->type) {
14096 case XML_SCHEMA_TYPE_SIMPLE:
14097 case XML_SCHEMA_TYPE_COMPLEX:
14098 xmlSchemaTypeFixup(item, ctxt, NULL);
14099 break;
14100 default:
14101 break;
14102 }
14103 }
14104 /*
14105 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014106 * hold by simple type components only (and
14107 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014108 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014109 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014110 for (i = 0; i < nbItems; i++) {
14111 item = items[i];
14112 switch (item->type) {
14113 case XML_SCHEMA_TYPE_SIMPLE:
14114 case XML_SCHEMA_TYPE_COMPLEX:
14115 xmlSchemaCheckDefaults(item, ctxt, NULL);
14116 break;
14117 default:
14118 break;
14119 }
14120 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014121 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014122 /*
14123 * Build the content model for complex types.
14124 */
14125 for (i = 0; i < nbItems; i++) {
14126 item = items[i];
14127 switch (item->type) {
14128 case XML_SCHEMA_TYPE_COMPLEX:
14129 xmlSchemaBuildContentModel(item, ctxt, NULL);
14130 break;
14131 default:
14132 break;
14133 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014134 }
14135 /*
14136 * Validate value contraint values.
14137 */
14138 for (i = 0; i < nbItems; i++) {
14139 item = items[i];
14140 switch (item->type) {
14141 case XML_SCHEMA_TYPE_ATTRIBUTE:
14142 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14143 break;
14144 case XML_SCHEMA_TYPE_ELEMENT:
14145 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14146 break;
14147 default:
14148 break;
14149 }
14150 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014151}
14152
14153/**
14154 * xmlSchemaAssembleByLocation:
14155 * @pctxt: a schema parser context
14156 * @vctxt: a schema validation context
14157 * @schema: the existing schema
14158 * @node: the node that fired the assembling
14159 * @nsName: the namespace name of the new schema
14160 * @location: the location of the schema
14161 *
14162 * Expands an existing schema by an additional schema.
14163 *
14164 * Returns 0 if the new schema is correct, a positive error code
14165 * number otherwise and -1 in case of an internal or API error.
14166 */
14167static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014168xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14169 xmlSchemaPtr schema,
14170 xmlNodePtr node,
14171 const xmlChar *nsName,
14172 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014173{
14174 const xmlChar *targetNs, *oldtns;
14175 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014176 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014177 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014178 xmlSchemaParserCtxtPtr pctxt;
14179
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014180 /*
14181 * This should be used:
14182 * 1. on <import>(s)
14183 * 2. if requested by the validated instance
14184 * 3. if requested via the API
14185 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014186 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014187 return (-1);
14188 /*
14189 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014190 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014191 if ((vctxt->pctxt == NULL) &&
14192 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14193 xmlSchemaVErr(vctxt, node,
14194 XML_SCHEMAV_INTERNAL,
14195 "Internal error: xmlSchemaAssembleByLocation, "
14196 "failed to create a temp. parser context.\n",
14197 NULL, NULL);
14198 return (-1);
14199 }
14200 pctxt = vctxt->pctxt;
14201 /*
14202 * Set the counter to produce unique names for anonymous items.
14203 */
14204 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014205 /*
14206 * Acquire the schema document.
14207 */
14208 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14209 nsName, location, &doc, &targetNs, 0);
14210 if (ret != 0) {
14211 if (doc != NULL)
14212 xmlFreeDoc(doc);
14213 } else if (doc != NULL) {
14214 docElem = xmlDocGetRootElement(doc);
14215 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014216 * Create new assemble info.
14217 */
14218 if (pctxt->assemble == NULL) {
14219 pctxt->assemble = xmlSchemaNewAssemble();
14220 if (pctxt->assemble == NULL) {
14221 xmlSchemaVErrMemory(vctxt,
14222 "Memory error: xmlSchemaAssembleByLocation, "
14223 "allocating assemble info", NULL);
14224 xmlFreeDoc(doc);
14225 return (-1);
14226 }
14227 }
14228 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014229 * Save and reset the context & schema.
14230 */
14231 oldflags = schema->flags;
14232 oldtns = schema->targetNamespace;
14233 olddoc = schema->doc;
14234
14235 xmlSchemaClearSchemaDefaults(schema);
14236 schema->targetNamespace = targetNs;
14237 /* schema->nbCurItems = 0; */
14238 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014239 pctxt->ctxtType = NULL;
14240 pctxt->parentItem = NULL;
14241
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014242 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14243 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014244 xmlSchemaPostSchemaAssembleFixup(pctxt);
14245 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014246 * Set the counter of items.
14247 */
14248 schema->counter = pctxt->counter;
14249 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014250 * Free the list of assembled components.
14251 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014252 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014253 /*
14254 * Restore the context & schema.
14255 */
14256 schema->flags = oldflags;
14257 schema->targetNamespace = oldtns;
14258 schema->doc = olddoc;
14259 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014260 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014261 return (ret);
14262}
14263
14264/**
14265 * xmlSchemaAssembleByXSIAttr:
14266 * @vctxt: a schema validation context
14267 * @xsiAttr: an xsi attribute
14268 * @noNamespace: whether a schema with no target namespace is exptected
14269 *
14270 * Expands an existing schema by an additional schema using
14271 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14272 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14273 * must be set to 1.
14274 *
14275 * Returns 0 if the new schema is correct, a positive error code
14276 * number otherwise and -1 in case of an internal or API error.
14277 */
14278static int
14279xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14280 xmlAttrPtr xsiAttr,
14281 int noNamespace)
14282{
14283 xmlChar *value;
14284 const xmlChar *cur, *end;
14285 const xmlChar *nsname = NULL, *location;
14286 int count = 0;
14287 int ret = 0;
14288
14289 if (xsiAttr == NULL) {
14290 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14291 NULL, NULL,
14292 "Internal error: xmlSchemaAssembleByXSIAttr, "
14293 "bad arguments", NULL);
14294 return (-1);
14295 }
14296 /*
14297 * Parse the value; we will assume an even number of values
14298 * to be given (this is how Xerces and XSV work).
14299 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014300 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014301 cur = value;
14302 do {
14303 if (noNamespace != 1) {
14304 /*
14305 * Get the namespace name.
14306 */
14307 while (IS_BLANK_CH(*cur))
14308 cur++;
14309 end = cur;
14310 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14311 end++;
14312 if (end == cur)
14313 break;
14314 count++;
14315 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14316 cur = end;
14317 }
14318 /*
14319 * Get the URI.
14320 */
14321 while (IS_BLANK_CH(*cur))
14322 cur++;
14323 end = cur;
14324 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14325 end++;
14326 if (end == cur)
14327 break;
14328 count++;
14329 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014330 cur = end;
14331 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014332 xsiAttr->parent, nsname, location);
14333 if (ret == -1) {
14334 xmlSchemaVCustomErr(vctxt,
14335 XML_SCHEMAV_INTERNAL,
14336 (xmlNodePtr) xsiAttr, NULL,
14337 "Internal error: xmlSchemaAssembleByXSIAttr, "
14338 "assembling schemata", NULL);
14339 if (value != NULL)
14340 xmlFree(value);
14341 return (-1);
14342 }
14343 } while (*cur != 0);
14344 if (value != NULL)
14345 xmlFree(value);
14346 return (ret);
14347}
14348
14349/**
14350 * xmlSchemaAssembleByXSIElem:
14351 * @vctxt: a schema validation context
14352 * @elem: an element node possibly holding xsi attributes
14353 * @noNamespace: whether a schema with no target namespace is exptected
14354 *
14355 * Assembles an existing schema by an additional schema using
14356 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14357 * of the given @elem.
14358 *
14359 * Returns 0 if the new schema is correct, a positive error code
14360 * number otherwise and -1 in case of an internal or API error.
14361 */
14362static int
14363xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14364 xmlNodePtr elem)
14365{
14366 int ret = 0, retNs = 0;
14367 xmlAttrPtr attr;
14368
14369 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14370 if (attr != NULL) {
14371 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14372 if (retNs == -1)
14373 return (-1);
14374 }
14375 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14376 if (attr != NULL) {
14377 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14378 if (ret == -1)
14379 return (-1);
14380 }
14381 if (retNs != 0)
14382 return (retNs);
14383 else
14384 return (ret);
14385}
14386
Daniel Veillard4255d502002-04-16 15:50:10 +000014387/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014388 * xmlSchemaValidateCallback:
14389 * @ctxt: a schema validation context
14390 * @name: the name of the element detected (might be NULL)
14391 * @type: the type
14392 *
14393 * A transition has been made in the automata associated to an element
14394 * content model
14395 */
14396static void
14397xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014398 const xmlChar * name ATTRIBUTE_UNUSED,
14399 xmlSchemaTypePtr type, xmlNodePtr node)
14400{
Daniel Veillard4255d502002-04-16 15:50:10 +000014401 xmlSchemaTypePtr oldtype = ctxt->type;
14402 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014403
Daniel Veillard4255d502002-04-16 15:50:10 +000014404#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014405 xmlGenericError(xmlGenericErrorContext,
14406 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014407 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014408#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014409 /*
14410 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14411 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014412 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014413 ctxt->node = node;
14414 ctxt->cur = node->children;
14415 /*
14416 * Assemble new schemata using xsi.
14417 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014418 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014419 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014420
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014421 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14422 if (ret == -1) {
14423 xmlSchemaVCustomErr(ctxt,
14424 XML_SCHEMAV_INTERNAL,
14425 ctxt->node, NULL,
14426 "Internal error: xmlSchemaValidateElement, "
14427 "assembling schema by xsi", NULL);
14428 return;
14429 }
14430 /*
14431 * NOTE: We won't react on schema parser errors here.
14432 * TODO: But a warning would be nice.
14433 */
14434 }
14435 switch (type->type) {
14436 case XML_SCHEMA_TYPE_ELEMENT: {
14437 /*
14438 * NOTE: The build of the content model
14439 * (xmlSchemaBuildAContentModel) ensures that the element
14440 * declaration (and not a reference to it) will be given.
14441 */
14442 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14443 /*
14444 * This is paranoid coding ;-)... it should not
14445 * happen here any more.
14446 */
14447 xmlSchemaVCustomErr(ctxt,
14448 XML_SCHEMAV_INTERNAL,
14449 node, NULL,
14450 "Internal error: xmlSchemaValidateCallback, "
14451 "element declaration 'reference' encountered, "
14452 "but an element declaration was expected",
14453 NULL);
14454 return;
14455 }
14456 xmlSchemaValidateElementByDeclaration(ctxt,
14457 (xmlSchemaElementPtr) type);
14458 break;
14459 }
14460 case XML_SCHEMA_TYPE_ANY:
14461 xmlSchemaValidateElementByWildcard(ctxt, type);
14462 break;
14463 default:
14464 break;
14465 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014466 ctxt->type = oldtype;
14467 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014468}
Daniel Veillard4255d502002-04-16 15:50:10 +000014469
Daniel Veillard01fa6152004-06-29 17:04:39 +000014470/**
14471 * xmlSchemaValidateSimpleTypeValue:
14472 * @ctxt: a schema validation context
14473 * @value: the value to be validated
14474 * @fireErrors: shall errors be reported?
14475 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014476 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014477 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014478 *
14479 * Validates a value by the given type (user derived or built-in).
14480 *
14481 * Returns 0 if the value is valid, a positive error code
14482 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014483 */
14484static int
14485xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014486 xmlSchemaTypePtr type,
14487 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014488 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014489 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014490 int normalize,
14491 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014492{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014493 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014494 int ret = 0;
14495 xmlChar *normValue = NULL;
14496 int wtsp;
14497
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014498 node = ctxt->node;
14499 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014500 wtsp = ctxt->valueWS;
14501 /*
14502 * Normalize the value.
14503 */
14504 if (normalize &&
14505 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14506 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14507
14508 if ((norm != -1) && (norm > ctxt->valueWS)) {
14509 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14510 normValue = xmlSchemaCollapseString(value);
14511 else
14512 normValue = xmlSchemaWhiteSpaceReplace(value);
14513 ctxt->valueWS = norm;
14514 if (normValue != NULL)
14515 value = (const xmlChar *) normValue;
14516 }
14517 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014518 /*
14519 * The nodes of a content must be checked only once,
14520 * this is not working since list types will fire this
14521 * multiple times.
14522 */
14523 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14524 xmlNodePtr cur = ctxt->cur;
14525
14526 do {
14527 switch (cur->type) {
14528 case XML_TEXT_NODE:
14529 case XML_CDATA_SECTION_NODE:
14530 case XML_PI_NODE:
14531 case XML_COMMENT_NODE:
14532 case XML_XINCLUDE_START:
14533 case XML_XINCLUDE_END:
14534 break;
14535 case XML_ENTITY_REF_NODE:
14536 case XML_ENTITY_NODE:
14537 /* TODO: Scour the entities for illegal nodes. */
14538 TODO break;
14539 case XML_ELEMENT_NODE: {
14540 /* NOTE: Changed to an internal error, since the
14541 * existence of an element node will be already checked in
14542 * xmlSchemaValidateElementBySimpleType and in
14543 * xmlSchemaValidateElementByComplexType.
14544 */
14545 xmlSchemaVCustomErr(ctxt,
14546 XML_SCHEMAV_INTERNAL,
14547 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14548 node, type,
14549 "Element '%s' found in simple type content",
14550 cur->name);
14551 return (XML_SCHEMAV_INTERNAL);
14552 }
14553 case XML_ATTRIBUTE_NODE:
14554 case XML_DOCUMENT_NODE:
14555 case XML_DOCUMENT_TYPE_NODE:
14556 case XML_DOCUMENT_FRAG_NODE:
14557 case XML_NOTATION_NODE:
14558 case XML_HTML_DOCUMENT_NODE:
14559 case XML_DTD_NODE:
14560 case XML_ELEMENT_DECL:
14561 case XML_ATTRIBUTE_DECL:
14562 case XML_ENTITY_DECL:
14563 case XML_NAMESPACE_DECL:
14564#ifdef LIBXML_DOCB_ENABLED
14565 case XML_DOCB_DOCUMENT_NODE:
14566#endif
14567 xmlSchemaVCustomErr(ctxt,
14568 XML_SCHEMAV_INTERNAL,
14569 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14570 node, NULL,
14571 "Node of unexpected type found in simple type content",
14572 NULL);
14573 return (XML_SCHEMAV_INTERNAL);
14574 }
14575 cur = cur->next;
14576 } while (cur != NULL);
14577 }
14578
William M. Brack2f2a6632004-08-20 23:09:47 +000014579 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14580 xmlSchemaTypePtr base, anyType;
14581
14582 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14583
14584 base = type->baseType;
14585 while ((base != NULL) &&
14586 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14587 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14588 (base != anyType)) {
14589 base = base->baseType;
14590 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014591 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014592 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014593 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014594 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14595 "validating complex type '%s'\n",
14596 type->name, NULL);
14597 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14598 /*
14599 * Check facets.
14600 */
14601 /*
14602 * This is somehow not nice, since if an error occurs
14603 * the reported type will be the complex type; the spec
14604 * wants a simple type to be created on the complex type
14605 * if it has a simple content. For now we have to live with
14606 * it.
14607 */
14608 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14609 value, 0, fireErrors);
14610 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014611 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014612 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14613 "validating facets of complex type '%s'\n",
14614 type->name, NULL);
14615 } else if (ret > 0) {
14616 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014617 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014618 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014619 }
14620 }
14621 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014622
14623 if (ctxt->value != NULL) {
14624 xmlSchemaFreeValue(ctxt->value);
14625 ctxt->value = NULL;
14626 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014627 /*
14628 * STREAM-READ-CHILDREN.
14629 */
14630 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014631 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014632 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14633 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14634 else
14635 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014636 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014637 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014638 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014639 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014640 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014641 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014642 }
14643 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14644 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14645 * a literal in the ·lexical space· of {base type definition}
14646 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014647 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014648 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014649 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014651 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014652 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014653 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014654 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014655 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014656 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014657 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014658 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014659 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014660 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014661 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14662 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014663 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014664 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014665 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014666 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014667 type->name, NULL);
14668 } else if (ret > 0) {
14669 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014670 /*
14671 Disabled, since the facet validation already reports errors.
14672 if (fireErrors)
14673 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14674 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014675 }
14676 }
14677 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14678
14679 xmlSchemaTypePtr tmpType;
14680 const xmlChar *cur, *end;
14681 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014682 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014683
14684 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14685 * of white space separated tokens, each of which ·match·es a literal
14686 * in the ·lexical space· of {item type definition}
14687 */
14688
Daniel Veillardc0826a72004-08-10 14:17:33 +000014689 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014690 cur = value;
14691 do {
14692 while (IS_BLANK_CH(*cur))
14693 cur++;
14694 end = cur;
14695 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14696 end++;
14697 if (end == cur)
14698 break;
14699 tmp = xmlStrndup(cur, end - cur);
14700 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014701 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014702 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014703 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014704 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014705 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14706 "validating an item of list simple type '%s'\n",
14707 type->name, NULL);
14708 break;
14709 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014710 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014711 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014712 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014713 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014714 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014715 cur = end;
14716 } while (*cur != 0);
14717 /*
14718 * Check facets.
14719 */
14720 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014721 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014722 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014723 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014724 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014725 } else if ((ret == 0) && (applyFacets)) {
14726 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14727 value, len, fireErrors);
14728 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014729 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014730 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14731 "validating facets of list simple type '%s'\n",
14732 type->name, NULL);
14733 } else if (ret > 0) {
14734 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014735 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014736 Disabled, since the facet validation already reports errors.
14737 if (fireErrors)
14738 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014739 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014740 }
14741
Daniel Veillard01fa6152004-06-29 17:04:39 +000014742 }
14743 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14744 xmlSchemaTypeLinkPtr memberLink;
14745
14746 /*
14747 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14748 * not apply directly; however, the normalization behavior of ·union·
14749 * types is controlled by the value of whiteSpace on that one of the
14750 * ·memberTypes· against which the ·union· is successfully validated.
14751 *
14752 * This means that the value is normalized by the first validating
14753 * member type, then the facets of the union type are applied. This
14754 * needs changing of the value!
14755 */
14756
14757 /*
14758 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14759 * literal in the ·lexical space· of at least one member of
14760 * {member type definitions}
14761 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014762#ifdef DEBUG_UNION_VALIDATION
14763 printf("Union ST : '%s'\n", (const char *) type->name);
14764 printf(" fireErrors : %d\n", fireErrors);
14765 printf(" applyFacets: %d\n", applyFacets);
14766#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014767 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14768 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014769 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014770 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014771 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014772 type->name, NULL);
14773 ret = -1;
14774 }
14775 if (ret == 0) {
14776 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014777 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14778 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014779 if ((ret <= 0) || (ret == 0))
14780 break;
14781 memberLink = memberLink->next;
14782 }
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 members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014787 type->name, NULL);
14788 } else if (ret > 0) {
14789 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
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 }
14793 }
14794 /*
14795 * Apply facets (pattern, enumeration).
14796 */
14797 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14798 int mws;
14799 /*
14800 * The normalization behavior of ·union· types is controlled by
14801 * the value of whiteSpace on that one of the ·memberTypes·
14802 * against which the ·union· is successfully validated.
14803 */
14804 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014805 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014806 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14807 "the value was already normalized for the union simple "
14808 "type '%s'.\n", type->name, NULL);
14809 }
14810 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14811 if (mws > ctxt->valueWS) {
14812 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14813 normValue = xmlSchemaCollapseString(value);
14814 else
14815 normValue = xmlSchemaWhiteSpaceReplace(value);
14816 if (normValue != NULL)
14817 value = (const xmlChar *) normValue;
14818 }
14819
14820 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14821 value, 0, fireErrors);
14822 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014823 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014824 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14825 "validating facets of union simple type '%s'\n",
14826 type->name, NULL);
14827 } else if (ret > 0) {
14828 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14829 /*
14830 if (fireErrors)
14831 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14832 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014833 }
14834 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014835 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014836 ctxt->valueWS = wtsp;
14837 if (normValue != NULL)
14838 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014839 return (ret);
14840}
14841
14842/**
14843 * xmlSchemaValidateSimpleTypeElement:
14844 * @ctxt: a schema validation context
14845 * @node: the element node to be validated.
14846 *
14847 * Validate the element against a simple type.
14848 *
14849 * Returns 0 if the element is valid, a positive error code
14850 * number otherwise and -1 in case of an internal or API error.
14851 */
14852static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014853xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014854 xmlSchemaTypePtr type,
14855 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014856{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014857 xmlSchemaTypePtr oldtype;
14858 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014859 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014860 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014861 int ret = 0, retval = 0;
14862
Daniel Veillard01fa6152004-06-29 17:04:39 +000014863 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014864 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
14865 "Internal error: xmlSchemaValidateElementBySimpleType, "
14866 "bad arguments", NULL);
14867 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014868 }
14869
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014870 oldtype = ctxt->type;
14871 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014872 /*
14873 * cvc-type: 3.1.2 The element information item must have no element
14874 * information item [children].
14875 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014876 /*
14877 * STREAM: Child nodes are processed.
14878 */
14879 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014880 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014881 /*
14882 * TODO: Entities, will they produce elements as well?
14883 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014884 if (cur->type == XML_ELEMENT_NODE) {
14885 xmlSchemaVCustomErr(ctxt,
14886 XML_SCHEMAV_CVC_TYPE_3_1_2,
14887 node, type,
14888 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014889 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014890 }
14891 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014892 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014893
Daniel Veillard01fa6152004-06-29 17:04:39 +000014894 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014895 * cvc-type 3.1.1:
14896 *
14897 * The attributes of must be empty, excepting those whose namespace name
14898 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
14899 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014900 */
14901 /*
14902 * STREAM: Attribute nodes are processed.
14903 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014904 attr = node->properties;
14905 while (attr != NULL) {
14906 if ((attr->ns == NULL) ||
14907 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
14908 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
14909 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
14910 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
14911 (!xmlStrEqual
14912 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014913 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014914 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
14915 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014916 }
14917 attr = attr->next;
14918 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014919 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014920 * This will skip validation if the type is 'anySimpleType' and
14921 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014922 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014923 if ((valSimpleContent == 1) &&
14924 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14925 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014926 xmlChar *value;
14927
14928 value = xmlNodeGetContent(node);
14929 /*
14930 * NOTE: This call will not check the content nodes, since
14931 * this should be checked here already.
14932 */
14933 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14934 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014935 if (value != NULL)
14936 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014937 if (retval != 0)
14938 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014939 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014940 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014941 return (ret);
14942}
Daniel Veillard4255d502002-04-16 15:50:10 +000014943
14944/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014945 * xmlSchemaValQNameAcquire:
14946 * @value: the lexical represantation of the QName value
14947 * @node: the node to search for the corresponding namespace declaration
14948 * @nsName: the resulting namespace name if found
14949 *
14950 * Checks that a value conforms to the lexical space of the type QName;
14951 * if valid, the corresponding namespace name is searched and retured
14952 * as a copy in @nsName. The local name is returned in @localName as
14953 * a copy.
14954 *
14955 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14956 * namespace declaration was found in scope; -1 in case of an internal or
14957 * API error.
14958 */
14959static int
14960xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14961 xmlChar **nsName, xmlChar **localName)
14962{
14963 int ret;
14964 xmlChar *local = NULL;
14965
14966 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14967 return (-1);
14968 *nsName = NULL;
14969 *localName = NULL;
14970 ret = xmlValidateQName(value, 1);
14971 if (ret == 0) {
14972 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014973 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014974
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014975 /*
14976 * NOTE: xmlSplitQName2 will return a duplicated
14977 * string.
14978 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014979 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014980 if (local == NULL)
14981 local = xmlStrdup(value);
14982 ns = xmlSearchNs(node->doc, node, prefix);
14983 /*
14984 * A namespace need not to be found if the prefix is NULL.
14985 */
14986 if (ns != NULL) {
14987 /*
14988 * TODO: Is it necessary to duplicate the URI here?
14989 */
14990 *nsName = xmlStrdup(ns->href);
14991 } else if (prefix != NULL) {
14992 xmlFree(prefix);
14993 if (local != NULL)
14994 xmlFree(local);
14995 return (2);
14996 }
14997 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014998 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014999 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015000 } else
15001 return (1);
15002 return (ret);
15003}
15004
15005/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015006 * xmlSchemaHasElemContent:
15007 * @node: the node
15008 *
15009 * Scours the content of the given node for element
15010 * nodes.
15011 *
15012 * Returns 1 if an element node is found,
15013 * 0 otherwise.
15014 */
15015static int
15016xmlSchemaHasElemContent(xmlNodePtr node)
15017{
15018 if (node == NULL)
15019 return (0);
15020 node = node->children;
15021 while (node != NULL) {
15022 if (node->type == XML_ELEMENT_NODE)
15023 return (1);
15024 node = node->next;
15025 }
15026 return (0);
15027}
15028/**
15029 * xmlSchemaHasElemOrCharContent:
15030 * @node: the node
15031 *
15032 * Scours the content of the given node for element
15033 * and character nodes.
15034 *
15035 * Returns 1 if an element or character node is found,
15036 * 0 otherwise.
15037 */
15038static int
15039xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15040{
15041 if (node == NULL)
15042 return (0);
15043 node = node->children;
15044 while (node != NULL) {
15045 switch (node->type) {
15046 case XML_ELEMENT_NODE:
15047 /*
15048 * TODO: Ask Daniel if these are all character nodes.
15049 */
15050 case XML_TEXT_NODE:
15051 case XML_CDATA_SECTION_NODE:
15052 /*
15053 * TODO: How XML_ENTITY_NODEs evaluated?
15054 */
15055 case XML_ENTITY_REF_NODE:
15056 case XML_ENTITY_NODE:
15057 return (1);
15058 break;
15059 default:
15060 break;
15061 }
15062 node = node->next;
15063 }
15064 return (0);
15065}
15066
15067
15068/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015069 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015070 * @ctxt: a schema validation context
15071 * @node: the top node.
15072 *
15073 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015074 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015075 *
15076 * Returns 0 if the element is schemas valid, a positive error code
15077 * number otherwise and -1 in case of internal or API error.
15078 */
15079static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015080xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15081 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015082{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015083 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015084 int ret = 0;
15085 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015086 xmlAttrPtr attr;
15087 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015088 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015089
15090 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015091 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15092 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015093 * Note that @elemDecl will be the declaration and never the
15094 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015095 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015096
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015097 if (ctxt == NULL) {
15098 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15099 "Internal error: xmlSchemaValidateElementByDeclaration, "
15100 "bad arguments.\n",
15101 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015102 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015103 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015104
15105 elem = ctxt->node;
15106
15107 /*
15108 * cvc-elt (3.3.4) : 1
15109 */
15110 if (elemDecl == NULL) {
15111 xmlSchemaVCustomErr(ctxt,
15112 XML_SCHEMAV_CVC_ELT_1,
15113 elem, NULL,
15114 "No matching declaration available", NULL);
15115 return (ctxt->err);
15116 }
15117 /*
15118 * cvc-elt (3.3.4) : 2
15119 */
15120 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15121 xmlSchemaVCustomErr(ctxt,
15122 XML_SCHEMAV_CVC_ELT_2,
15123 elem, NULL,
15124 "The element declaration is abstract", NULL);
15125 return (ctxt->err);
15126 }
15127
15128 /*
15129 * cvc-elt (3.3.4) : 3
15130 * Handle 'xsi:nil'.
15131 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015132
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015133 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015134 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015135 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15136 ctxt->node = (xmlNodePtr) attr;
15137 ctxt->cur = attr->children;
15138 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15139 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15140 BAD_CAST attrValue, 1, 1, 1, 1);
15141 ctxt->node = elem;
15142 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15143 if (ret < 0) {
15144 xmlSchemaVCustomErr(ctxt,
15145 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015146 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015147 "Internal error: xmlSchemaValidateElementByDeclaration, "
15148 "validating the attribute 'xsi:nil'", NULL);
15149 if (attrValue != NULL)
15150 xmlFree(attrValue);
15151 return (-1);
15152 }
15153 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015154 /*
15155 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015156 */
15157 xmlSchemaVCustomErr(ctxt,
15158 XML_SCHEMAV_CVC_ELT_3_1,
15159 elem, NULL,
15160 "The element is not 'nillable'", NULL);
15161 } else {
15162 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015163 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015164 ret = 0;
15165 /*
15166 * cvc-elt (3.3.4) : 3.2.1
15167 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015168 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15169 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015170 xmlSchemaVCustomErr(ctxt,
15171 XML_SCHEMAV_CVC_ELT_3_2_1,
15172 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015173 elem, (xmlSchemaTypePtr) elemDecl,
15174 "The 'nilled' element must have no character or "
15175 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015176 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15177 }
15178 /*
15179 * cvc-elt (3.3.4) : 3.2.2
15180 */
15181 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15182 (elemDecl->value != NULL)) {
15183 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15184 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015185 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015186 "There is a fixed value constraint defined for "
15187 "the 'nilled' element", NULL);
15188 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15189 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015190 if (ret == 0)
15191 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015192 }
15193 }
15194 if (attrValue != NULL)
15195 xmlFree(attrValue);
15196 }
15197
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015198
15199 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015200 /*
15201 * cvc-elt (3.3.4) : 4
15202 * Handle 'xsi:type'.
15203 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015204
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015205 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15206 if (attr != NULL) {
15207 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015208
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015209 /*
15210 * TODO: We should report a *warning* that the type was overriden
15211 * by the instance.
15212 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015213
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015214 /*
15215 * cvc-elt (3.3.4) : 4.1
15216 */
15217 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15218 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15219 &nsName, &local);
15220 if (ret < 0) {
15221 xmlSchemaVCustomErr(ctxt,
15222 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015223 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015224 "Internal error: xmlSchemaValidateElementByDeclaration, "
15225 "validating the attribute 'xsi:type'", NULL);;
15226 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015227 FREE_AND_NULL(nsName)
15228 FREE_AND_NULL(local)
15229 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015230 } else if (ret == 1) {
15231 xmlSchemaVSimpleTypeErr(ctxt,
15232 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15233 (xmlNodePtr) attr, attrValue,
15234 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15235 } else if (ret == 2) {
15236 xmlSchemaVCustomErr(ctxt,
15237 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15238 (xmlNodePtr) attr,
15239 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15240 "The QName value '%s' has no "
15241 "corresponding namespace declaration in scope",
15242 attrValue);
15243 } else {
15244 /*
15245 * cvc-elt (3.3.4) : 4.2
15246 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015247 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15248 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015249 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015250
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015251 xmlSchemaVCustomErr(ctxt,
15252 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015253 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015254 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15255 "The value %s does not resolve to a type "
15256 "definition",
15257 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15258 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015259 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015260 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015261 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015262 */
15263 }
15264 }
15265 FREE_AND_NULL(attrValue)
15266 FREE_AND_NULL(nsName)
15267 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015268 }
15269 /* TODO: Change the handling of missing types according to
15270 * the spec.
15271 */
15272 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015273 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015274 XML_SCHEMAV_CVC_TYPE_1,
15275 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015276 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015277 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015278 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015279
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015280 /*
15281 * TODO: Since this should be already checked by the content model automaton,
15282 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15283 * has been changed to XML_SCHEMAV_INTERNAL.
15284 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015285 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015286 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015287 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015288 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015289 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015290 "Element %s: missing child %s\n",
15291 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015292 }
15293 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015294 }
15295 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015296 /*
15297 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015298 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015299 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015300 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015301 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015302 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015303 "Element %s: missing child %s found %s\n",
15304 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015305 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015306 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015307 */
15308 if (elemHasContent == -1)
15309 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15310 /*
15311 * cvc-elt (3.3.4) : 5
15312 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015313 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015314 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015315 * cvc-elt (3.3.4) : 5.1
15316 * If the declaration has a {value constraint},
15317 * the item has neither element nor character [children] and
15318 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015319 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015320 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15321 /*
15322 * cvc-elt (3.3.4) : 5.1.1
15323 * If the ·actual type definition· is a ·local type definition·
15324 * then the canonical lexical representation of the {value constraint}
15325 * value must be a valid default for the ·actual type definition· as
15326 * defined in Element Default Valid (Immediate) (§3.3.6).
15327 */
15328 /*
15329 * NOTE: 'local' above means types aquired by xsi:type.
15330 */
15331 ret = 0;
15332 if (actualType != elemDecl->subtypes) {
15333 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15334 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15335 elemDecl->value, NULL);
15336 if (ret < 0) {
15337 xmlSchemaVCustomErr(ctxt,
15338 XML_SCHEMAV_INTERNAL,
15339 elem, actualType,
15340 "Internal error: xmlSchemaValidateElementByDeclaration, "
15341 "validating a default value", NULL);
15342 return (-1);
15343 }
15344 }
15345 /*
15346 * cvc-elt (3.3.4) : 5.1.2
15347 * The element information item with the canonical lexical
15348 * representation of the {value constraint} value used as its
15349 * ·normalized value· must be ·valid· with respect to the
15350 * ·actual type definition· as defined by Element Locally Valid (Type)
15351 * (§3.3.4).
15352 */
15353 /*
15354 * Disable validation of the simple content, since it was already
15355 * done above.
15356 */
15357 if (ret == 0) {
15358 if (actualType != elemDecl->subtypes)
15359 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15360 else
15361 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15362 ctxt->node = elem;
15363 if (ret < 0) {
15364 xmlSchemaVCustomErr(ctxt,
15365 XML_SCHEMAV_INTERNAL,
15366 elem, actualType,
15367 "Internal error: xmlSchemaValidateElementByDeclaration, "
15368 "validating against the type", NULL);
15369 return (-1);
15370 }
15371 /*
15372 * PSVI: Create a text node on the instance element.
15373 */
15374 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15375 xmlNodePtr textChild;
15376
15377 textChild = xmlNewText(elemDecl->value);
15378 if (textChild == NULL) {
15379 xmlSchemaVCustomErr(ctxt,
15380 XML_SCHEMAV_INTERNAL,
15381 elem, actualType,
15382 "Internal error: xmlSchemaValidateElementByDeclaration, "
15383 "could not create a default text node for the instance",
15384 NULL);
15385 } else
15386 xmlAddChild(elem, textChild);
15387 }
15388 }
15389
15390 } else {
15391 /*
15392 * 5.2.1 The element information item must be ·valid· with respect
15393 * to the ·actual type definition· as defined by Element Locally
15394 * Valid (Type) (§3.3.4).
15395 */
15396 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15397 ctxt->node = elem;
15398 if (ret < 0) {
15399 xmlSchemaVCustomErr(ctxt,
15400 XML_SCHEMAV_INTERNAL,
15401 elem, actualType,
15402 "Internal error: xmlSchemaValidateElementByDeclaration, "
15403 "validating a default value", NULL);
15404 return (-1);
15405 }
15406 /*
15407 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15408 * not applied, all of the following must be true:
15409 */
15410
15411 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15412 /*
15413 * 5.2.2.1 The element information item must have no element
15414 * information item [children].
15415 *
15416 * TODO REDUNDANT: If the actual type exists, the above call to
15417 * xmlSchemaValidateElementByType will already check for element
15418 * nodes.
15419 */
15420 if (xmlSchemaHasElemContent(elem)) {
15421 xmlSchemaVCustomErr(ctxt,
15422 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15423 elem, (xmlSchemaTypePtr) elemDecl,
15424 "Elements in the content are not allowed if it is "
15425 "constrained by a fixed value", NULL);
15426 } else {
15427 /*
15428 * 5.2.2.2 The appropriate case among the following must
15429 * be true:
15430 */
15431
15432 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15433 xmlChar *value;
15434 /*
15435 * 5.2.2.2.1 If the {content type} of the ·actual type
15436 * definition· is mixed, then the *initial value* of the
15437 * item must match the canonical lexical representation
15438 * of the {value constraint} value.
15439 *
15440 * ... the *initial value* of an element information
15441 * item is the string composed of, in order, the
15442 * [character code] of each character information item in
15443 * the [children] of that element information item.
15444 */
15445 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15446 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15447 /*
15448 * TODO: Report invalid & expected values as well.
15449 * TODO: Implement the cononical stuff.
15450 */
15451 xmlSchemaVCustomErr(ctxt,
15452 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15453 elem, (xmlSchemaTypePtr) elemDecl,
15454 "The value does not match the cononical "
15455 "lexical representation of the fixed constraint",
15456 NULL);
15457 }
15458 if (value != NULL)
15459 xmlFree(value);
15460 } else if ((actualType->contentType ==
15461 XML_SCHEMA_CONTENT_SIMPLE) ||
15462 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15463 xmlChar *value;
15464
15465 /*
15466 * 5.2.2.2.2 If the {content type} of the ·actual type
15467 * definition· is a simple type definition, then the
15468 * *actual value* of the item must match the canonical
15469 * lexical representation of the {value constraint} value.
15470 */
15471 /*
15472 * TODO: *actual value* is the normalized value, impl. this.
15473 * TODO: Report invalid & expected values as well.
15474 * TODO: Implement the cononical stuff.
15475 *
15476 */
15477 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15478 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15479 xmlSchemaVCustomErr(ctxt,
15480 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15481 elem, (xmlSchemaTypePtr) elemDecl,
15482 "The normalized value does not match the cononical "
15483 "lexical representation of the fixed constraint",
15484 NULL);
15485 }
15486 if (value != NULL)
15487 xmlFree(value);
15488
15489 }
15490 /*
15491 * TODO: What if the content type is not 'mixed' or simple?
15492 */
15493
15494 }
15495
15496 }
15497 }
15498
15499 /*
15500 * TODO: 6 The element information item must be ·valid· with respect to each of
15501 * the {identity-constraint definitions} as per Identity-constraint
15502 * Satisfied (§3.11.4).
15503 */
15504
15505 /*
15506 * TODO: 7 If the element information item is the ·validation root·, it must be
15507 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15508 */
15509
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015510 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015511}
15512
Daniel Veillard4255d502002-04-16 15:50:10 +000015513/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015514 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015515 * @ctxt: a schema validation context
15516 * @node: the top node.
15517 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015518 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15519 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015520 *
15521 * Returns 0 if the element is valid, a positive error code
15522 * number otherwise and -1 in case of an internal error.
15523 */
15524static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015525xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15526 xmlSchemaWildcardPtr wild,
15527 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015528{
15529 const xmlChar *uri;
15530 int ret = 0;
15531 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015532
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015533 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015534 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15535 if (ret == -1) {
15536 xmlSchemaVCustomErr(ctxt,
15537 XML_SCHEMAV_INTERNAL,
15538 ctxt->node, NULL,
15539 "Internal error: xmlSchemaValidateElement, "
15540 "assembling schema by xsi", NULL);
15541 return (-1);
15542 }
15543 /*
15544 * NOTE: We won't react on schema parser errors here.
15545 * TODO: But a warning would be nice.
15546 */
15547 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015548 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15549 xmlSchemaElementPtr decl = NULL;
15550
15551 if (node->ns != NULL)
15552 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15553 node->name, node->ns->href, NULL);
15554 else
15555 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15556 if (decl != NULL) {
15557 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015558 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015559 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015560 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015561 "Internal error: xmlSchemaValidateAnyInternal, "
15562 "validating an element in the context of a wildcard.",
15563 NULL, NULL);
15564 } else if (ret > 0)
15565 return (ret);
15566 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15567 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015568 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015569 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015570 return (ctxt->err);
15571 }
15572 }
15573 if (node->children != NULL) {
15574 child = node->children;
15575 do {
15576 if (child->type == XML_ELEMENT_NODE) {
15577 if (child->ns != NULL)
15578 uri = child->ns->href;
15579 else
15580 uri = NULL;
15581 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015582 /* TODO: error code. */
15583 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015584 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015585 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015586 return (ctxt->err);
15587 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015588 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15589 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015590 if (ret != 0)
15591 return (ret);
15592 }
15593 child = child->next;
15594 } while (child != NULL);
15595 }
15596 return (0);
15597}
15598
15599/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015600 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015601 * @ctxt: a schema validation context
15602 *
15603 * Returns 0 if the element is valid, a positive error code
15604 * number otherwise and -1 in case of an internal or API error.
15605 */
15606static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015607xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15608 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015609{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015610 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15611 (ctxt->node == NULL)) {
15612 xmlSchemaVCustomErr(ctxt,
15613 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15614 "Internal error: xmlSchemaValidateElementByWildcard, "
15615 "bad arguments", NULL);
15616 return (-1);
15617 }
15618 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15619 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015620}
15621
15622/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015623 * xmlSchemaValidateAnyTypeContent:
15624 * @ctxt: a schema validation context
15625 * @node: the current element
15626 *
15627 * This one validates the content of an element of the type
15628 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15629 * thus elements in the subtree will be validated, if a corresponding
15630 * declaration in the schema exists.
15631 *
15632 * Returns 0 if the element and its subtree is valid, a positive error code
15633 * otherwise and -1 in case of an internal or API error.
15634 */
15635static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015636xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15637 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015638{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015639 xmlSchemaTypePtr oldtype;
15640 xmlNodePtr top, cur;
15641 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015642 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015643
15644 if ((type == NULL) || (ctxt->node == NULL))
15645 return (-1);
15646
15647 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015648 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015649
15650 oldtype = ctxt->type;
15651 top = ctxt->node;
15652 /*
15653 * STREAM: Child nodes are processed.
15654 */
15655 cur = ctxt->node->children;
15656 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015657 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015658 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015659 /*
15660 * The process contents of the wildcard is "lax", thus
15661 * we need to validate the element if a declaration
15662 * exists.
15663 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015664 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015665 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015666 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015667 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015668 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015669 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015670 ctxt->node = cur;
15671 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15672 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015673 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015674 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015675 "Internal error: xmlSchemaValidateAnyTypeContent, "
15676 "validating an element in the context of a wildcard.",
15677 NULL, NULL);
15678 return (ret);
15679 } else if (ret > 0)
15680 return (ret);
15681 skipContent = 1;
15682 }
15683 }
15684 /*
15685 * Browse the full subtree, deep first.
15686 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015687 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015688 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015689 cur = cur->children;
15690 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015691 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015692 cur = cur->next;
15693 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015694 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015695 while (cur != top) {
15696 if (cur->parent != NULL)
15697 cur = cur->parent;
15698 if ((cur != top) && (cur->next != NULL)) {
15699 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015700 break;
15701 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015702 if (cur->parent == NULL) {
15703 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015704 break;
15705 }
15706 }
15707 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015708 if (cur == top)
15709 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015710 } else
15711 break;
15712 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015713 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015714 return (0);
15715}
15716
15717/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015718 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015719 * @ctxt: a schema validation context
15720 * @node: the top node.
15721 *
15722 * Validate the content of an element expected to be a complex type type
15723 * xmlschema-1.html#cvc-complex-type
15724 * Validation Rule: Element Locally Valid (Complex Type)
15725 *
15726 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015727 * number otherwise and -1 in case of internal or API error.
15728 * Note on reported errors: Although it might be nice to report
15729 * the name of the simple/complex type, used to validate the content
15730 * of a node, it is quite unnecessary: for global defined types
15731 * the local name of the element is equal to the NCName of the type,
15732 * for local defined types it makes no sense to output the internal
15733 * computed name of the type. TODO: Instead, one should attach the
15734 * struct of the type involved to the error handler - this allows
15735 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015736 */
15737static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015738xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015739 xmlSchemaTypePtr type,
15740 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015741{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015742 xmlSchemaTypePtr oldtype;
15743 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015744 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015745 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015746 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015747
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015748 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15749 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015750
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015751 oldtype = ctxt->type;
15752 ctxt->type = type;
15753 elem = ctxt->node;
15754
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015755 /*
15756 * Verify the attributes
15757 */
15758 /*
15759 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015760 */
15761 /* NOTE: removed, since a check for abstract is
15762 * done in the cvc-type constraint.
15763 *
15764 *
15765 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15766 * xmlSchemaVComplexTypeErr(ctxt,
15767 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15768 * elem, type,
15769 * "The type definition is abstract");
15770 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15771 *}
15772 */
15773
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015774 attrs = ctxt->attr;
15775 attrTop = ctxt->attrTop;
15776 /*
15777 * STREAM: Attribute nodes are processed.
15778 */
15779 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15780 xmlSchemaValidateAttributes(ctxt, elem, type);
15781 if (ctxt->attr != NULL)
15782 xmlSchemaFreeAttributeStates(ctxt->attr);
15783 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015784 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015785
15786 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015787 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015788 * model was defined. Somehow ->contModel is always not NULL
15789 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015790 * TODO: Check if the obove still occurs.
15791 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015792 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015793 case XML_SCHEMA_CONTENT_EMPTY: {
15794 /*
15795 * 1 If the {content type} is empty, then the element information
15796 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015797 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015798 /*
15799 * TODO: Is the entity stuff correct?
15800 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015801 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015802 xmlSchemaVComplexTypeErr(ctxt,
15803 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015804 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015805 "Character or element content is not allowed, "
15806 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015808 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015809 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015810 case XML_SCHEMA_CONTENT_MIXED:
15811 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015812 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015813 /*
15814 * The type has 'anyType' as its base and no content model
15815 * is defined -> use 'anyType' as the type to validate
15816 * against.
15817 */
15818 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15819 /* TODO: Handle -1. */
15820 break;
15821 }
15822 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015823 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015824 {
15825 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015826
15827 /*
15828 * Content model check initialization.
15829 */
15830 if (type->contModel != NULL) {
15831 oldregexp = ctxt->regexp;
15832 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15833 (xmlRegExecCallbacks)
15834 xmlSchemaValidateCallback, ctxt);
15835#ifdef DEBUG_AUTOMATA
15836 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15837#endif
15838 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015839 /*
15840 * STREAM: Children are processed.
15841 */
15842 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015843 while (child != NULL) {
15844 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015845 if (child->ns != NULL)
15846 nsUri = child->ns->href;
15847 else
15848 nsUri = NULL;
15849 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015850 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015851 /*
15852 * URGENT TODO: Could we anchor an error report
15853 * here to notify of invalid elements?
15854 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015855#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000015856 if (ret < 0)
15857 xmlGenericError(xmlGenericErrorContext,
15858 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000015859 else
15860 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015861 " --> %s\n", child->name);
15862#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015863 if (ret < 0) {
15864 xmlSchemaVComplexTypeErr(ctxt,
15865 XML_SCHEMAV_ELEMENT_CONTENT,
15866 child, NULL/* type */,
15867 "This element is not expected");
15868 ret = 1;
15869 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015870 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
15871 /*
15872 * TODO: Ask Daniel if this are all character nodes.
15873 */
15874 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
15875 (child->type == XML_ENTITY_NODE) ||
15876 (child->type == XML_ENTITY_REF_NODE) ||
15877 (child->type == XML_CDATA_SECTION_NODE))) {
15878 /*
15879 * 2.3 If the {content type} is element-only, then the
15880 * element information item has no character information
15881 * item [children] other than those whose [character
15882 * code] is defined as a white space in [XML 1.0 (Second
15883 * Edition)].
15884 */
William M. Brack2f2a6632004-08-20 23:09:47 +000015885 xmlSchemaVComplexTypeErr(ctxt,
15886 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015887 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015888 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015889 "because the content type is element-only");
15890 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015891 break;
15892 }
15893 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015894 }
15895 /*
15896 * Content model check finalization.
15897 */
15898 if (type->contModel != NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015899 if (ret != 1) {
15900 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015901#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015902 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015903 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015904#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015905 if (ret == 0) {
15906 /* TODO: Hmm, can this one really happen? */
15907 xmlSchemaVComplexTypeErr(ctxt,
15908 XML_SCHEMAV_ELEMENT_CONTENT,
15909 elem, type, "Missing child element(s)");
15910 } else if (ret < 0) {
15911 xmlSchemaVComplexTypeErr(ctxt,
15912 XML_SCHEMAV_ELEMENT_CONTENT,
15913 elem, type, "Missing child element(s)");
15914#ifdef DEBUG_CONTENT
15915 } else {
15916 xmlGenericError(xmlGenericErrorContext,
15917 "Element %s content check succeeded\n",
15918 elem->name);
15919
15920#endif
15921 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015922 }
15923 xmlRegFreeExecCtxt(ctxt->regexp);
15924 ctxt->regexp = oldregexp;
15925 }
15926 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015927 break;
15928 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015929 case XML_SCHEMA_CONTENT_BASIC:
15930 /*
15931 * If the simple content was already validated
15932 * (e.g. a default value), the content need not
15933 * to be validated again.
15934 */
15935 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015936 xmlChar *value = NULL;
15937 /*
15938 * We hit a complexType with a simpleContent resolving
15939 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000015940 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015941 /*
15942 * 2.2 If the {content type} is a simple type definition,
15943 * then the element information item has no element
15944 * information item [children], and the ·normalized value·
15945 * of the element information item is ·valid· with respect
15946 * to that simple type definition as defined by String
15947 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015948 */
15949 /*
15950 * STREAM: Children are processed.
15951 */
15952 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015953 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015954 /*
15955 * TODO: Could the entity stuff produce elements
15956 * as well?
15957 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015958 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015959 xmlSchemaVComplexTypeErr(ctxt,
15960 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015961 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015962 "Element content is not allowed, because "
15963 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015964 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15965 break;
15966 }
15967 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015968 }
15969 ctxt->node = elem;
15970 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015971 if (ret == 0) {
15972 /*
15973 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000015974 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015975 /*
15976 * STREAM: Children are processed.
15977 */
15978 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015979 value = NULL;
15980 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015981 value = xmlNodeGetContent(elem);
15982 /*
15983 * URGENT TODO: Should facets for the simple type validation be
15984 * disabled, if the derivation of facets for complex types
15985 * is implemented?
15986 */
15987 /*
15988 * NOTE: This call won't check the correct types of the
15989 * content nodes, since this should be done here.
15990 */
15991 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015992 if (ret > 0) {
15993 /*
15994 * NOTE: Although an error will be reported by
15995 * xmlSchemaValidateSimpleTypeValue, the spec wants
15996 * a specific complex type error to be reported
15997 * additionally.
15998 */
15999 xmlSchemaVComplexTypeErr(ctxt,
16000 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016001 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016002 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016003 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16004 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016005 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016006 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016007 "Element '%s': Error while validating character "
16008 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016009 elem->name, type->name);
16010 if (value != NULL)
16011 xmlFree(value);
16012 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016013 return (-1);
16014 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016015 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016016 if (ret == 0) {
16017 /*
16018 * Apply facets of the complexType. Be sure to pass the
16019 * built-in type to xmlSchemaValidateFacetsInternal.
16020 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016021 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000016022 * are used, or if the facets, defined by this complex type,
16023 * are to be used only. This here applies both facet sets.
16024 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016025
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016026 ret = xmlSchemaValidateFacetsInternal(ctxt,
16027 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016028 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016029 xmlSchemaVComplexTypeErr(ctxt,
16030 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016031 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016032 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016033 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16034 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016035 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016036 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016037 "Element '%s': Error while validating character "
16038 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000016039 "apply facets.\n",
16040 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016041 if (value != NULL)
16042 xmlFree(value);
16043 ctxt->type = oldtype;
16044 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016045 }
16046 }
16047 if (value != NULL)
16048 xmlFree(value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016049
Daniel Veillard01fa6152004-06-29 17:04:39 +000016050 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016051 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016052 default:
16053 TODO xmlGenericError(xmlGenericErrorContext,
16054 "unimplemented content type %d\n",
16055 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016056 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016057 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016058 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016059}
16060
16061/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016062 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016063 * @ctxt: a schema validation context
16064 * @elem: an element
16065 * @type: the list of type declarations
16066 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016067 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016068 *
16069 * Returns 0 if the element is schemas valid, a positive error code
16070 * number otherwise and -1 in case of internal or API error.
16071 */
16072static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016073xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016074 xmlSchemaTypePtr type,
16075 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016076{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016077 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016078
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016079
16080 if ((ctxt == NULL) || (type == NULL)) {
16081 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16082 "Internal error: xmlSchemaValidateElementByType, "
16083 "bad arguments", NULL);
16084 return (-1);
16085 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016086 /*
16087 * This one is called by "xmlSchemaValidateElementByDeclaration".
16088 * It will forward to the proper validation
16089 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016090 */
16091 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016092 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016093 XML_SCHEMAV_CVC_TYPE_1,
16094 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016095 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016096 return (XML_SCHEMAV_CVC_TYPE_1);
16097 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016098
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016099 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016100 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016101 XML_SCHEMAV_CVC_TYPE_2,
16102 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016103 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016104 return (XML_SCHEMAV_CVC_TYPE_2);
16105 }
16106
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016107 switch (type->type) {
16108 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016109 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16110 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016111 break;
16112 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016113 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16114 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016115 break;
16116 case XML_SCHEMA_TYPE_BASIC:
16117 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16118 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16119 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016120 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16121 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016122 break;
16123 default:
16124 ret = -1;
16125 break;
16126 }
16127 if (ret == -1)
16128 return (-1);
16129 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016130 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016131}
16132
16133
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016134static int
16135xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16136 xmlSchemaAttributePtr decl,
16137 xmlSchemaAttrStatePtr state,
16138 xmlAttrPtr attr)
16139{
16140 xmlChar *value;
16141 const xmlChar *defValue;
16142 xmlSchemaValPtr defVal;
16143 int fixed;
16144 int ret;
16145
16146 if (decl->subtypes == NULL) {
16147 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16148 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16149 }
16150 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16151 ctxt->node = (xmlNodePtr) attr;
16152 ctxt->cur = attr->children;
16153 /*
16154 * NOTE: This call also checks the content nodes for correct type.
16155 */
16156 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16157 value, 1, 1, 1, 1);
16158
16159 /*
16160 * Handle 'fixed' attributes.
16161 */
16162 if (ret > 0) {
16163 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16164 /*
16165 * NOTE: Fixed value constraints will be not
16166 * applied if the value was invalid, because:
16167 * 1. The validation process does not return a precomputed
16168 * value.
16169 * 2. An invalid value implies a violation of a fixed
16170 * value constraint.
16171 */
16172 } else if (ret == 0) {
16173 state->state = XML_SCHEMAS_ATTR_CHECKED;
16174 if (xmlSchemaGetEffectiveValueConstraint(decl,
16175 &fixed, &defValue, &defVal) && (fixed == 1)) {
16176 /*
16177 * cvc-au : Attribute Locally Valid (Use)
16178 * For an attribute information item to be·valid·
16179 * with respect to an attribute use its ·normalized
16180 * value· must match the canonical lexical representation
16181 * of the attribute use's {value constraint} value, if it
16182 * is present and fixed.
16183 */
16184 /*
16185 * NOTE: the validation context holds in ctxt->value the
16186 * precomputed value of the attribute; well for some types,
16187 * fallback to string comparison if no computed value
16188 * exists.
16189 */
16190 if (((ctxt->value != NULL) &&
16191 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16192 ((ctxt->value == NULL) &&
16193 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16194 state->state =
16195 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16196 }
16197 }
16198 }
16199 if (value != NULL) {
16200 xmlFree(value);
16201 }
16202 return (ret);
16203}
16204
Daniel Veillard4255d502002-04-16 15:50:10 +000016205/**
16206 * xmlSchemaValidateAttributes:
16207 * @ctxt: a schema validation context
16208 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016209 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016210 *
16211 * Validate the attributes of an element.
16212 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016213 * 1. Existent, invalid attributes are reported in the form
16214 * "prefix:localName".
16215 * Reason: readability - it is easier to find the actual XML
16216 * representation of the attributes QName.
16217 * 2. Missing attributes are reported in the form
16218 * {"URI", "localName"}.
16219 * This is necessary, since the the prefix need not to be declared
16220 * at all, and thus is not computable.
16221 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016222 * Returns 0 if the element is schemas valid, a positive error code
16223 * number otherwise and -1 in case of internal or API error.
16224 */
16225static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016226xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016227{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016228 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016229 int ret;
16230 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016231 const xmlChar *defValue;
16232 xmlSchemaValPtr defVal;
16233 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016234 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016235 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016236 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016237 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016238 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016239 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016240#ifdef DEBUG_ATTR_VALIDATION
16241 int redundant = 0;
16242#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016243
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016244
Daniel Veillardc0826a72004-08-10 14:17:33 +000016245 /*
16246 * Allow all attributes if the type is anyType.
16247 */
16248 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16249 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016250
16251 oldnode = ctxt->node;
16252 if (type != NULL)
16253 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016254 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016255 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016256 attrDecl = attrUse->attr;
16257#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016258 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016259 printf("attr use - use: %d\n", attrDecl->occurs);
16260#endif
16261 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16262
16263 if (curState->decl == attrUse->attr) {
16264#ifdef DEBUG_ATTR_VALIDATION
16265 redundant = 1;
16266#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016267 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016268 attr = curState->attr;
16269#ifdef DEBUG_ATTR_VALIDATION
16270 printf("attr - name: %s\n", attr->name);
16271 if (attr->ns != NULL)
16272 printf("attr - ns: %s\n", attr->ns->href);
16273 else
16274 printf("attr - ns: none\n");
16275#endif
16276 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016277 if (attr == NULL)
16278 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016279 if (attrDecl->ref != NULL) {
16280 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016281 continue;
16282 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016283 if ((attrDecl->refNs == NULL) ||
16284 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016285 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016286 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016287 continue;
16288 }
16289 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016290 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016291 continue;
16292 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016293 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016294 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016295 if (attr->ns == NULL) {
16296 /*
William M. Bracke7091952004-05-11 15:09:58 +000016297 * accept an unqualified attribute only if the target
16298 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016299 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016300 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016301 /*
16302 * This check was removed, since the target namespace
16303 * was evaluated during parsing and already took
16304 * "attributeFormDefault" into account.
16305 */
16306 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016307 continue;
16308 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016309 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016310 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016311 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016312 attr->ns->href))
16313 continue;
16314 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016315 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016316#ifdef DEBUG_ATTR_VALIDATION
16317 printf("found\n");
16318#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016319 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016320 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016321 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016322 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016323 if (!found) {
16324 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16325 xmlSchemaAttrStatePtr tmp;
16326
Daniel Veillard3646d642004-06-02 19:19:14 +000016327#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016328 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016329#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016330 /*
16331 * Add a new dummy attribute state.
16332 */
16333 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16334 if (tmp == NULL) {
16335 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16336 ctxt->node = oldnode;
16337 return (-1);
16338 }
16339 tmp->attr = NULL;
16340 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16341 tmp->decl = attrDecl;
16342 tmp->next = NULL;
16343
16344 if (reqAttrStates == NULL) {
16345 reqAttrStates = tmp;
16346 reqAttrStatesTop = tmp;
16347 } else {
16348 reqAttrStatesTop->next = tmp;
16349 reqAttrStatesTop = tmp;
16350 }
16351 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16352 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16353 &fixed, &defValue, &defVal))) {
16354 xmlSchemaAttrStatePtr tmp;
16355 /*
16356 * Handle non existent default/fixed attributes.
16357 */
16358 tmp = (xmlSchemaAttrStatePtr)
16359 xmlMalloc(sizeof(xmlSchemaAttrState));
16360 if (tmp == NULL) {
16361 xmlSchemaVErrMemory(ctxt,
16362 "registering schema specified attributes", NULL);
16363 ctxt->node = oldnode;
16364 return (-1);
16365 }
16366 tmp->attr = NULL;
16367 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16368 tmp->decl = attrDecl;
16369 tmp->value = defValue;
16370 tmp->next = NULL;
16371
16372 if (defAttrStates == NULL) {
16373 defAttrStates = tmp;
16374 defAttrStates = tmp;
16375 } else {
16376 defAttrStates->next = tmp;
16377 defAttrStatesTop = tmp;
16378 }
16379 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016380 }
16381 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016382 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016383 /*
16384 * Add required attributes to the attribute states of the context.
16385 */
16386 if (reqAttrStates != NULL) {
16387 if (ctxt->attr == NULL) {
16388 ctxt->attr = reqAttrStates;
16389 } else {
16390 ctxt->attrTop->next = reqAttrStates;
16391 }
16392 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016393 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016394 /*
16395 * Process wildcards.
16396 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016397
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016398 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016399#ifdef DEBUG_ATTR_VALIDATION
16400 xmlSchemaWildcardNsPtr ns;
16401 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016402 if (type->attributeWildcard->processContents ==
16403 XML_SCHEMAS_ANY_LAX)
16404 printf("processContents: lax\n");
16405 else if (type->attributeWildcard->processContents ==
16406 XML_SCHEMAS_ANY_STRICT)
16407 printf("processContents: strict\n");
16408 else
16409 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016410 if (type->attributeWildcard->any)
16411 printf("type: any\n");
16412 else if (type->attributeWildcard->negNsSet != NULL) {
16413 printf("type: negated\n");
16414 if (type->attributeWildcard->negNsSet->value == NULL)
16415 printf("ns: (absent)\n");
16416 else
16417 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16418 } else if (type->attributeWildcard->nsSet != NULL) {
16419 printf("type: set\n");
16420 ns = type->attributeWildcard->nsSet;
16421 while (ns != NULL) {
16422 if (ns->value == NULL)
16423 printf("ns: (absent)\n");
16424 else
16425 printf("ns: %s\n", ns->value);
16426 ns = ns->next;
16427 }
16428 } else
16429 printf("empty\n");
16430
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016431
16432#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016433 curState = ctxt->attr;
16434 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016435 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16436 if (curState->attr->ns != NULL)
16437 nsURI = curState->attr->ns->href;
16438 else
16439 nsURI = NULL;
16440 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16441 nsURI)) {
16442 /*
16443 * Handle processContents.
16444 */
16445 if ((type->attributeWildcard->processContents ==
16446 XML_SCHEMAS_ANY_LAX) ||
16447 (type->attributeWildcard->processContents ==
16448 XML_SCHEMAS_ANY_STRICT)) {
16449
16450 attr = curState->attr;
16451 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016452 attr->name, nsURI);
16453 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016454 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016455 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016456 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016457 } else if (type->attributeWildcard->processContents ==
16458 XML_SCHEMAS_ANY_LAX) {
16459 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16460 }
16461 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016462 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016463 }
16464 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016465 curState = curState->next;
16466 }
16467 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016468
Daniel Veillardc0826a72004-08-10 14:17:33 +000016469 /*
16470 * Report missing and illegal attributes.
16471 */
16472 if (ctxt->attr != NULL) {
16473 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016474 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016475 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16476 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016477 if (curState->decl != NULL) {
16478 if (curState->decl->ref != NULL)
16479 attrDecl = curState->decl->refDecl;
16480 else
16481 attrDecl = curState->decl;
16482 } else
16483 attrDecl = NULL;
16484 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16485 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16486 } else if (curState->state ==
16487 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16488 xmlSchemaVCustomErr(ctxt,
16489 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16490 (xmlNodePtr) attr,
16491 (xmlSchemaTypePtr) attrDecl,
16492 "The type definition is absent",
16493 NULL);
16494 } else if (curState->state ==
16495 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16496 xmlSchemaVCustomErr(ctxt,
16497 XML_SCHEMAV_CVC_AU,
16498 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16499 "The value does not match the fixed value "
16500 "constraint", NULL);
16501 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016502 /* TODO: "prohibited" won't ever be touched here!.
16503 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16504 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016505 /*
16506 * TODO: One might report different error messages
16507 * for the following errors.
16508 */
16509 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016510 xmlSchemaVIllegalAttrErr(ctxt,
16511 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16512 } else {
16513 xmlSchemaVIllegalAttrErr(ctxt,
16514 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16515 }
16516 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016517 }
16518 curState = curState->next;
16519 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016520 }
16521
16522 /*
16523 * Add missing default/fixed attributes.
16524 */
16525 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16526 curState = defAttrStates;
16527 while (curState != NULL) {
16528 attrDecl = curState->decl;
16529 if (attrDecl->ref != NULL)
16530 attrDecl = attrDecl->refDecl;
16531 /*
16532 * PSVI: Add a new attribute node to the current element.
16533 */
16534 if (attrDecl->targetNamespace == NULL) {
16535 xmlNewProp(elem, attrDecl->name, curState->value);
16536 } else {
16537 xmlNsPtr ns;
16538
16539 ns = xmlSearchNsByHref(elem->doc, elem,
16540 attrDecl->targetNamespace);
16541 if (ns == NULL) {
16542 xmlChar prefix[12];
16543 int counter = 1;
16544
16545 attr = curState->attr;
16546 /*
16547 * Create a namespace declaration on the validation
16548 * root node if no namespace declaration is in scope.
16549 */
16550 snprintf((char *) prefix, sizeof(prefix), "p");
16551 /*
16552 * This is somehow not performant, since the ancestor
16553 * axis beyond @elem will be searched as well.
16554 */
16555 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16556 while (ns != NULL) {
16557 if (counter > 1000) {
16558 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16559 XML_SCHEMAV_INTERNAL,
16560 "Internal error: xmlSchemaValidateAttributes, "
16561 "could not compute a ns prefix for "
16562 "default/fixed attribute '%s'.\n",
16563 attrDecl->name, NULL);
16564
16565 break;
16566 }
16567 snprintf((char *) prefix,
16568 sizeof(prefix), "p%d", counter++);
16569 ns = xmlSearchNs(elem->doc, elem,
16570 BAD_CAST prefix);
16571 }
16572 if (ns == NULL) {
16573 ns = xmlNewNs(ctxt->validationRoot,
16574 attrDecl->targetNamespace, BAD_CAST prefix);
16575 xmlNewNsProp(elem, ns, attrDecl->name,
16576 curState->value);
16577 }
16578 } else {
16579 xmlNewNsProp(elem, ns, attrDecl->name,
16580 curState->value);
16581 }
16582 }
16583 curState = curState->next;
16584 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016585 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016586 if (defAttrStates != NULL)
16587 xmlSchemaFreeAttributeStates(defAttrStates);
16588
Daniel Veillard3646d642004-06-02 19:19:14 +000016589#ifdef DEBUG_ATTR_VALIDATION
16590 if (redundant)
16591 xmlGenericError(xmlGenericErrorContext,
16592 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16593 type->name);
16594#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016595 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016596 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016597}
16598
16599/**
16600 * xmlSchemaValidateElement:
16601 * @ctxt: a schema validation context
16602 * @elem: an element
16603 *
16604 * Validate an element in a tree
16605 *
16606 * Returns 0 if the element is schemas valid, a positive error code
16607 * number otherwise and -1 in case of internal or API error.
16608 */
16609static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016610xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016611{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016612 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016613 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016614
Daniel Veillardc0826a72004-08-10 14:17:33 +000016615 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016616 * This one is called by xmlSchemaValidateDocument and
16617 * xmlSchemaValidateOneElement.
16618 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016619 if (ctxt->schema == NULL) {
16620 /*
16621 * No schema was specified at time of creation of the validation
16622 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16623 * of the instance to build a schema.
16624 */
16625 if (ctxt->pctxt == NULL)
16626 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16627 if (ctxt->pctxt == NULL)
16628 return (-1);
16629 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16630 if (ctxt->schema == NULL)
16631 return (-1);
16632 /* TODO: assign user data. */
16633 ctxt->pctxt->error = ctxt->error;
16634 ctxt->pctxt->warning = ctxt->warning;
16635 ctxt->xsiAssemble = 1;
16636 } else
16637 ctxt->xsiAssemble = 0;
16638 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16639 * ctxt->xsiAssemble = 1;
16640 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016641 /*
16642 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016643 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016644 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016645 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16646 if (ret == -1) {
16647 xmlSchemaVCustomErr(ctxt,
16648 XML_SCHEMAV_INTERNAL,
16649 ctxt->node, NULL,
16650 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016651 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016652 }
16653 /*
16654 * NOTE: We won't react on schema parser errors here.
16655 * TODO: But a warning would be nice.
16656 */
16657 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016658 if (ret != -1) {
16659 if (ctxt->node->ns != NULL)
16660 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16661 ctxt->node->ns->href);
16662 else
16663 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16664
16665 if (elemDecl == NULL) {
16666 xmlSchemaVCustomErr(ctxt,
16667 XML_SCHEMAV_CVC_ELT_1,
16668 ctxt->node, NULL,
16669 "No matching global declaration available", NULL);
16670 ret = XML_SCHEMAV_CVC_ELT_1;
16671 } else {
16672 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16673 if (ret < 0) {
16674 xmlSchemaVCustomErr(ctxt,
16675 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16676 "Internal error: xmlSchemaValidateElement, "
16677 "calling validation by declaration", NULL);
16678 }
16679 }
16680 }
16681 /* ctxt->xsiAssemble = 0; */
16682 if (ctxt->xsiAssemble) {
16683 if (ctxt->schema != NULL) {
16684 xmlSchemaFree(ctxt->schema);
16685 ctxt->schema = NULL;
16686 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016687 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016688 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016689}
16690
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016691
Daniel Veillard4255d502002-04-16 15:50:10 +000016692/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016693 * xmlSchemaValidateOneElement:
16694 * @ctxt: a schema validation context
16695 * @elem: an element node
16696 *
16697 * Validate a branch of a tree, starting with the given @elem.
16698 *
16699 * Returns 0 if the element and its subtree is valid, a positive error
16700 * code number otherwise and -1 in case of an internal or API error.
16701 */
16702int
16703xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16704{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016705 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016706 return (-1);
16707
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016708 if (ctxt->schema == NULL) {
16709 xmlSchemaVErr(ctxt, NULL,
16710 XML_SCHEMAV_INTERNAL,
16711 "API error: xmlSchemaValidateOneElement, "
16712 "no schema specified.\n", NULL, NULL);
16713 return (-1);
16714 }
16715
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016716 ctxt->doc = elem->doc;
16717 ctxt->err = 0;
16718 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016719 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016720 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016721 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016722}
16723
16724/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016725 * xmlSchemaValidateDocument:
16726 * @ctxt: a schema validation context
16727 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016728 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016729 *
16730 * Validate a document tree in memory.
16731 *
16732 * Returns 0 if the document is schemas valid, a positive error code
16733 * number otherwise and -1 in case of internal or API error.
16734 */
16735static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016736xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16737{
Daniel Veillard4255d502002-04-16 15:50:10 +000016738 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016739
Daniel Veillard4255d502002-04-16 15:50:10 +000016740 root = xmlDocGetRootElement(doc);
16741 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016742 xmlSchemaVCustomErr(ctxt,
16743 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16744 (xmlNodePtr) doc, NULL,
16745 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016746 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016747 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016748 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016749 /*
16750 * Okay, start the recursive validation
16751 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016752 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016753 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016754 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016755
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016756 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016757}
16758
16759/************************************************************************
16760 * *
16761 * SAX Validation code *
16762 * *
16763 ************************************************************************/
16764
16765/************************************************************************
16766 * *
16767 * Validation interfaces *
16768 * *
16769 ************************************************************************/
16770
16771/**
16772 * xmlSchemaNewValidCtxt:
16773 * @schema: a precompiled XML Schemas
16774 *
16775 * Create an XML Schemas validation context based on the given schema
16776 *
16777 * Returns the validation context or NULL in case of error
16778 */
16779xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016780xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16781{
Daniel Veillard4255d502002-04-16 15:50:10 +000016782 xmlSchemaValidCtxtPtr ret;
16783
16784 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16785 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016786 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016787 return (NULL);
16788 }
16789 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016790 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016791 ret->attrTop = NULL;
16792 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016793 return (ret);
16794}
16795
16796/**
16797 * xmlSchemaFreeValidCtxt:
16798 * @ctxt: the schema validation context
16799 *
16800 * Free the resources associated to the schema validation context
16801 */
16802void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016803xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16804{
Daniel Veillard4255d502002-04-16 15:50:10 +000016805 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016806 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016807 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016808 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016809 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016810 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016811 if (ctxt->pctxt != NULL) {
16812 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16813 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016814 xmlFree(ctxt);
16815}
16816
16817/**
16818 * xmlSchemaSetValidErrors:
16819 * @ctxt: a schema validation context
16820 * @err: the error function
16821 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016822 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016823 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016824 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016825 */
16826void
16827xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016828 xmlSchemaValidityErrorFunc err,
16829 xmlSchemaValidityWarningFunc warn, void *ctx)
16830{
Daniel Veillard4255d502002-04-16 15:50:10 +000016831 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016832 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016833 ctxt->error = err;
16834 ctxt->warning = warn;
16835 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016836 if (ctxt->pctxt != NULL)
16837 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000016838}
16839
16840/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016841 * xmlSchemaGetValidErrors:
16842 * @ctxt: a XML-Schema validation context
16843 * @err: the error function result
16844 * @warn: the warning function result
16845 * @ctx: the functions context result
16846 *
16847 * Get the error and warning callback informations
16848 *
16849 * Returns -1 in case of error and 0 otherwise
16850 */
16851int
16852xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
16853 xmlSchemaValidityErrorFunc * err,
16854 xmlSchemaValidityWarningFunc * warn, void **ctx)
16855{
16856 if (ctxt == NULL)
16857 return (-1);
16858 if (err != NULL)
16859 *err = ctxt->error;
16860 if (warn != NULL)
16861 *warn = ctxt->warning;
16862 if (ctx != NULL)
16863 *ctx = ctxt->userData;
16864 return (0);
16865}
16866
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016867
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016868/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016869 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016870 * @ctxt: a schema validation context
16871 * @options: a combination of xmlSchemaValidOption
16872 *
16873 * Sets the options to be used during the validation.
16874 *
16875 * Returns 0 in case of success, -1 in case of an
16876 * API error.
16877 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016878int
16879xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
16880 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016881
16882{
16883 int i;
16884
16885 if (ctxt == NULL)
16886 return (-1);
16887 /*
16888 * WARNING: Change the start value if adding to the
16889 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016890 * TODO: Is there an other, more easy to maintain,
16891 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016892 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016893 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016894 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016895 xmlSchemaVErr(ctxt, NULL,
16896 XML_SCHEMAV_INTERNAL,
16897 "Internal error: xmlSchemaSetValidOptions, "
16898 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016899 return (-1);
16900 }
16901 }
16902 ctxt->options = options;
16903 return (0);
16904}
16905
16906/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016907 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016908 * @ctxt: a schema validation context
16909 *
16910 * Returns the option combination of the validation context.
16911 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016912int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016913xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
16914
16915{
16916 if (ctxt == NULL)
16917 return (-1);
16918 else
16919 return (ctxt->options);
16920}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016921
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016922
Daniel Veillard259f0df2004-08-18 09:13:18 +000016923/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016924 * xmlSchemaValidateDoc:
16925 * @ctxt: a schema validation context
16926 * @doc: a parsed document tree
16927 *
16928 * Validate a document tree in memory.
16929 *
16930 * Returns 0 if the document is schemas valid, a positive error code
16931 * number otherwise and -1 in case of internal or API error.
16932 */
16933int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016934xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16935{
Daniel Veillard4255d502002-04-16 15:50:10 +000016936 int ret;
16937
16938 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016939 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016940
16941 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000016942 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016943 ctxt->nberrors = 0;
16944
16945 /*
16946 if (ctxt->schema == NULL) {
16947 xmlSchemaVErr(ctxt, NULL,
16948 XML_SCHEMAV_INTERNAL,
16949 "API error: xmlSchemaValidateDoc, "
16950 "no schema specified and assembling of schemata "
16951 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
16952 "is not enabled.\n", NULL, NULL);
16953 return (-1);
16954 }
16955 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016956 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016957 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016958}
16959
16960/**
16961 * xmlSchemaValidateStream:
16962 * @ctxt: a schema validation context
16963 * @input: the input to use for reading the data
16964 * @enc: an optional encoding information
16965 * @sax: a SAX handler for the resulting events
16966 * @user_data: the context to provide to the SAX handler.
16967 *
16968 * Validate a document tree in memory.
16969 *
16970 * Returns 0 if the document is schemas valid, a positive error code
16971 * number otherwise and -1 in case of internal or API error.
16972 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016973int
Daniel Veillard4255d502002-04-16 15:50:10 +000016974xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016975 xmlParserInputBufferPtr input, xmlCharEncoding enc,
16976 xmlSAXHandlerPtr sax, void *user_data)
16977{
Daniel Veillard4255d502002-04-16 15:50:10 +000016978 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016979 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016980 ctxt->input = input;
16981 ctxt->enc = enc;
16982 ctxt->sax = sax;
16983 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016984 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000016985}
16986
16987#endif /* LIBXML_SCHEMAS_ENABLED */