blob: dc432924eb26b9731cb32b0bde91a4f4e6c1dd3d [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000037
Daniel Veillarda84c0b32003-06-02 16:58:46 +000038/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000039
Daniel Veillard82bbbd42003-05-11 20:16:09 +000040/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000041
Daniel Veillard82bbbd42003-05-11 20:16:09 +000042/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000043
Daniel Veillard118aed72002-09-24 14:13:13 +000044/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000045
Daniel Veillard4255d502002-04-16 15:50:10 +000046/* #define DEBUG_AUTOMATA 1 */
47
Daniel Veillard3646d642004-06-02 19:19:14 +000048/* #define DEBUG_ATTR_VALIDATION 1 */
49
Daniel Veillardc0826a72004-08-10 14:17:33 +000050/* #define DEBUG_UNION_VALIDATION 1 */
51
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define UNBOUNDED (1 << 30)
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
William M. Brack2f2a6632004-08-20 23:09:47 +000059#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000060
Daniel Veillard4255d502002-04-16 15:50:10 +000061/*
62 * The XML Schemas namespaces
63 */
64static const xmlChar *xmlSchemaNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema";
66
67static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
68 "http://www.w3.org/2001/XMLSchema-instance";
69
Daniel Veillardc0826a72004-08-10 14:17:33 +000070static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
71 "Element decl.";
72static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
73 "Element ref.";
74static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
75 "Attribute decl.";
76static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
77 "Attribute ref.";
78static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000079 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000080static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000081 "complex type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000082
Daniel Veillard4255d502002-04-16 15:50:10 +000083#define IS_SCHEMA(node, type) \
84 ((node != NULL) && (node->ns != NULL) && \
85 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
86 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
87
Daniel Veillardc0826a72004-08-10 14:17:33 +000088#define FREE_AND_NULL(str) \
89 if (str != NULL) { \
90 xmlFree(str); \
91 str = NULL; \
92 }
93
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000094#define IS_ANYTYPE(item) \
95 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
96 (item->builtInType == XML_SCHEMAS_ANYTYPE))
97
98#define IS_COMPLEX_TYPE(item) \
99 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
100 (item->builtInType == XML_SCHEMAS_ANYTYPE))
101
102#define IS_SIMPLE_TYPE(item) \
103 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
104 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
105 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
106
Daniel Veillardc0826a72004-08-10 14:17:33 +0000107#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
108#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
109#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define XML_SCHEMAS_PARSE_ERROR 1
112
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000113#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000115
116/*
117* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
118* allow to assemble schemata with
119* the same target namespace from
120* different sources; otherwise, the first
121* encountered schema with a specific target
122* namespace will be used only *
123
124*
125* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
126* locate schemata to be imported
127* using the namespace name; otherwise
128* the location URI will be used */
129
130/*
131* xmlSchemaParserOption:
132*
133* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000135typedef enum {
136 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000137 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000138 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000139 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000140} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000141*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000142
143/*
144XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000145 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
146 int options);
147XMLPUBFUN int XMLCALL
148 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
149
150*/
151
152typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
153typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
154struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000155 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156 int nbItems; /* used for dynamic addition of schemata */
157 int sizeItems; /* used for dynamic addition of schemata */
158};
159
Daniel Veillard4255d502002-04-16 15:50:10 +0000160struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000161 void *userData; /* user specific data block */
162 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
163 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000164 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000165 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000166 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000167
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000168 xmlSchemaPtr topschema; /* The main schema */
169 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
170
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000171 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000172 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000173 int counter;
174
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000175 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000177 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000178
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179 const char *buffer;
180 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000181
Daniel Veillard4255d502002-04-16 15:50:10 +0000182 /*
183 * Used to build complex element content models
184 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000185 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 xmlAutomataStatePtr start;
187 xmlAutomataStatePtr end;
188 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000189
190 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000191 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000192 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
193 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194 xmlSchemaAssemblePtr assemble;
195 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000196 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000197};
198
199
200#define XML_SCHEMAS_ATTR_UNKNOWN 1
201#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000202#define XML_SCHEMAS_ATTR_PROHIBITED 3
203#define XML_SCHEMAS_ATTR_MISSING 4
204#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
205#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000206#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
207#define XML_SCHEMAS_ATTR_DEFAULT 8
Daniel Veillard4255d502002-04-16 15:50:10 +0000208
209typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
210typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
211struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000212 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000213 xmlAttrPtr attr;
214 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000215 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000216 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000217};
218
219/**
220 * xmlSchemaValidCtxt:
221 *
222 * A Schemas validation context
223 */
224
225struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *userData; /* user specific data block */
227 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
228 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000229 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000230
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000231 xmlSchemaPtr schema; /* The schema in use */
232 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlCharEncoding enc;
235 xmlSAXHandlerPtr sax;
236 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 xmlDocPtr myDoc;
239 int err;
240 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000241
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000242 xmlNodePtr node;
243 xmlNodePtr cur;
244 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000246 xmlRegExecCtxtPtr regexp;
247 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248
Daniel Veillard3646d642004-06-02 19:19:14 +0000249 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000250 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000251 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000252 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlNodePtr validationRoot;
255 xmlSchemaParserCtxtPtr pctxt;
256 int xsiAssemble;
Daniel Veillard4255d502002-04-16 15:50:10 +0000257};
258
Daniel Veillard1d913862003-11-21 00:28:39 +0000259/*
260 * These are the entries in the schemas importSchemas hash table
261 */
262typedef struct _xmlSchemaImport xmlSchemaImport;
263typedef xmlSchemaImport *xmlSchemaImportPtr;
264struct _xmlSchemaImport {
265 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000266 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000267 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000268 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000269};
Daniel Veillard4255d502002-04-16 15:50:10 +0000270
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000271/*
272 * These are the entries associated to includes in a schemas
273 */
274typedef struct _xmlSchemaInclude xmlSchemaInclude;
275typedef xmlSchemaInclude *xmlSchemaIncludePtr;
276struct _xmlSchemaInclude {
277 xmlSchemaIncludePtr next;
278
279 const xmlChar *schemaLocation;
280 xmlDocPtr doc;
281};
282
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000283typedef struct _xmlSchemaParticle xmlSchemaParticle;
284typedef xmlSchemaParticle *xmlSchemaParticlePtr;
285struct _xmlSchemaParticle {
286 xmlSchemaTypeType type;
287 xmlSchemaParticlePtr next; /* the next particle if in a list */
288 int minOccurs;
289 int maxOccurs;
290 xmlSchemaTypePtr term;
291};
292
293
294typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
295typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
296struct _xmlSchemaModelGroup {
297 xmlSchemaTypeType type;
298 int compositor; /* one of all, choice or sequence */
299 xmlSchemaParticlePtr particles; /* list of particles */
300 xmlSchemaAnnotPtr annot;
301};
302
303typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
304typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
305struct _xmlSchemaModelGroupDef {
306 xmlSchemaTypeType type;
307 const xmlChar *name;
308 const xmlChar *targetNamespace;
309 xmlSchemaModelGroupPtr modelGroup;
310 xmlSchemaAnnotPtr annot;
311};
312
Daniel Veillard4255d502002-04-16 15:50:10 +0000313/************************************************************************
314 * *
315 * Some predeclarations *
316 * *
317 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000319static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
320 xmlSchemaPtr schema,
321 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000322static void
323xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
324 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
325static const char *
326xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
327static int
328xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000329 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000330 const xmlChar *value,
331 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000332 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000333 int normalize,
334 int checkNodes);
335static int
336xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
337 xmlSchemaElementPtr elemDecl);
338static int
339xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
340 xmlSchemaTypePtr type);
341static int
342xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000343static int
344xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
345 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000346static void
347xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
348 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000349
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000350/************************************************************************
351 * *
352 * Datatype error handlers *
353 * *
354 ************************************************************************/
355
356/**
357 * xmlSchemaPErrMemory:
358 * @node: a context node
359 * @extra: extra informations
360 *
361 * Handle an out of memory condition
362 */
363static void
364xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
365 const char *extra, xmlNodePtr node)
366{
367 if (ctxt != NULL)
368 ctxt->nberrors++;
369 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
370 extra);
371}
372
373/**
374 * xmlSchemaPErr:
375 * @ctxt: the parsing context
376 * @node: the context node
377 * @error: the error code
378 * @msg: the error message
379 * @str1: extra data
380 * @str2: extra data
381 *
382 * Handle a parser error
383 */
384static void
385xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
386 const char *msg, const xmlChar * str1, const xmlChar * str2)
387{
388 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000389 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000390 void *data = NULL;
391
392 if (ctxt != NULL) {
393 ctxt->nberrors++;
394 channel = ctxt->error;
395 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000396 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000397 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000398 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000399 error, XML_ERR_ERROR, NULL, 0,
400 (const char *) str1, (const char *) str2, NULL, 0, 0,
401 msg, str1, str2);
402}
403
404/**
405 * xmlSchemaPErr2:
406 * @ctxt: the parsing context
407 * @node: the context node
408 * @node: the current child
409 * @error: the error code
410 * @msg: the error message
411 * @str1: extra data
412 * @str2: extra data
413 *
414 * Handle a parser error
415 */
416static void
417xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
418 xmlNodePtr child, int error,
419 const char *msg, const xmlChar * str1, const xmlChar * str2)
420{
421 if (child != NULL)
422 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
423 else
424 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
425}
426
Daniel Veillard01fa6152004-06-29 17:04:39 +0000427
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000428/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000429 * xmlSchemaPErrExt:
430 * @ctxt: the parsing context
431 * @node: the context node
432 * @error: the error code
433 * @strData1: extra data
434 * @strData2: extra data
435 * @strData3: extra data
436 * @msg: the message
437 * @str1: extra parameter for the message display
438 * @str2: extra parameter for the message display
439 * @str3: extra parameter for the message display
440 * @str4: extra parameter for the message display
441 * @str5: extra parameter for the message display
442 *
443 * Handle a parser error
444 */
445static void
446xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
447 const xmlChar * strData1, const xmlChar * strData2,
448 const xmlChar * strData3, const char *msg, const xmlChar * str1,
449 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
450 const xmlChar * str5)
451{
452
453 xmlGenericErrorFunc channel = NULL;
454 xmlStructuredErrorFunc schannel = NULL;
455 void *data = NULL;
456
457 if (ctxt != NULL) {
458 ctxt->nberrors++;
459 channel = ctxt->error;
460 data = ctxt->userData;
461 schannel = ctxt->serror;
462 }
463 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
464 error, XML_ERR_ERROR, NULL, 0,
465 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000466 (const char *) strData3, 0, 0, msg, str1, str2,
467 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000468}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000469
Daniel Veillard3646d642004-06-02 19:19:14 +0000470
471/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000472 * xmlSchemaVTypeErrMemory:
473 * @node: a context node
474 * @extra: extra informations
475 *
476 * Handle an out of memory condition
477 */
478static void
479xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
480 const char *extra, xmlNodePtr node)
481{
482 if (ctxt != NULL) {
483 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000484 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000485 }
486 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
487 extra);
488}
489
490/**
491 * xmlSchemaVErr3:
492 * @ctxt: the validation context
493 * @node: the context node
494 * @error: the error code
495 * @msg: the error message
496 * @str1: extra data
497 * @str2: extra data
498 * @str3: extra data
499 *
500 * Handle a validation error
501 */
502static void
503xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
504 const char *msg, const xmlChar *str1, const xmlChar *str2,
505 const xmlChar *str3)
506{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000507 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000508 xmlGenericErrorFunc channel = NULL;
509 void *data = NULL;
510
511 if (ctxt != NULL) {
512 ctxt->nberrors++;
513 ctxt->err = error;
514 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000515 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000516 data = ctxt->userData;
517 }
518 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000519 /* Removed, since the old schema error codes have been
520 * substituted for the global error codes.
521 *
522 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
523 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000524 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000525 error, XML_ERR_ERROR, NULL, 0,
526 (const char *) str1, (const char *) str2,
527 (const char *) str3, 0, 0,
528 msg, str1, str2, str3);
529}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000530
531/**
532 * xmlSchemaVErrExt:
533 * @ctxt: the validation context
534 * @node: the context node
535 * @error: the error code
536 * @msg: the message
537 * @str1: extra parameter for the message display
538 * @str2: extra parameter for the message display
539 * @str3: extra parameter for the message display
540 * @str4: extra parameter for the message display
541 * @str5: extra parameter for the message display
542 *
543 * Handle a validation error
544 */
545static void
546xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
547 const char *msg, const xmlChar * str1,
548 const xmlChar * str2, const xmlChar * str3,
549 const xmlChar * str4, const xmlChar * str5)
550{
551 xmlStructuredErrorFunc schannel = NULL;
552 xmlGenericErrorFunc channel = NULL;
553 void *data = NULL;
554
555 if (ctxt != NULL) {
556 ctxt->nberrors++;
557 ctxt->err = error;
558 channel = ctxt->error;
559 schannel = ctxt->serror;
560 data = ctxt->userData;
561 }
562 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000563 /* Removed, since the old schema error codes have been
564 * substituted for the global error codes.
565 *
566 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
567 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000568 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
569 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
570 msg, str1, str2, str3, str4, str5);
571}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572/**
573 * xmlSchemaVErr:
574 * @ctxt: the validation context
575 * @node: the context node
576 * @error: the error code
577 * @msg: the error message
578 * @str1: extra data
579 * @str2: extra data
580 *
581 * Handle a validation error
582 */
583static void
584xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
585 const char *msg, const xmlChar * str1, const xmlChar * str2)
586{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000587 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000588 xmlGenericErrorFunc channel = NULL;
589 void *data = NULL;
590
591 if (ctxt != NULL) {
592 ctxt->nberrors++;
593 ctxt->err = error;
594 channel = ctxt->error;
595 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000596 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000597 }
598 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000599 /* Removed, since the old schema error codes have been
600 * substituted for the global error codes.
601 *
602 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
603 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000604 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000605 error, XML_ERR_ERROR, NULL, 0,
606 (const char *) str1, (const char *) str2, NULL, 0, 0,
607 msg, str1, str2);
608}
Daniel Veillard4255d502002-04-16 15:50:10 +0000609
Daniel Veillardc0826a72004-08-10 14:17:33 +0000610/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000611 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000612 * @attr: the attribute declaration/use
613 *
614 * Returns the name of the attribute; if the attribute
615 * is a reference, the name of the referenced global type will be returned.
616 */
617static const xmlChar *
618xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
619{
620 if (attr->ref != NULL)
621 return(attr->ref);
622 else
623 return(attr->name);
624}
625
626/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000627 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000628 * @type: the type (element or attribute)
629 *
630 * Returns the target namespace URI of the type; if the type is a reference,
631 * the target namespace of the referenced type will be returned.
632 */
633static const xmlChar *
634xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
635{
636 if (attr->ref != NULL)
637 return (attr->refNs);
638 else
639 return(attr->targetNamespace);
640}
641
642/**
643 * xmlSchemaFormatNsUriLocal:
644 * @buf: the string buffer
645 * @uri: the namespace URI
646 * @local: the local name
647 *
648 * Returns a representation of the given URI used
649 * for error reports.
650 *
651 * Returns an empty string, if @ns is NULL, a formatted
652 * string otherwise.
653 */
654static const xmlChar*
655xmlSchemaFormatNsUriLocal(xmlChar **buf,
656 const xmlChar *uri, const xmlChar *local)
657{
658 if (*buf != NULL)
659 xmlFree(*buf);
660 if (uri == NULL) {
661 *buf = xmlStrdup(BAD_CAST "{'");
662 *buf = xmlStrcat(*buf, local);
663 } else {
664 *buf = xmlStrdup(BAD_CAST "{'");
665 *buf = xmlStrcat(*buf, uri);
666 *buf = xmlStrcat(*buf, BAD_CAST "', '");
667 *buf = xmlStrcat(*buf, local);
668 }
669 *buf = xmlStrcat(*buf, BAD_CAST "'}");
670 return ((const xmlChar *) *buf);
671}
672
673/**
674 * xmlSchemaFormatNsPrefixLocal:
675 * @buf: the string buffer
676 * @ns: the namespace
677 * @local: the local name
678 *
679 * Returns a representation of the given URI used
680 * for error reports.
681 *
682 * Returns an empty string, if @ns is NULL, a formatted
683 * string otherwise.
684 */
685static const xmlChar*
686xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
687 xmlNsPtr ns, const xmlChar *local)
688{
689 if (*buf != NULL) {
690 xmlFree(*buf);
691 *buf = NULL;
692 }
693 if ((ns == NULL) || (ns->prefix == NULL))
694 return(local);
695 else {
696 *buf = xmlStrdup(ns->prefix);
697 *buf = xmlStrcat(*buf, BAD_CAST ":");
698 *buf = xmlStrcat(*buf, local);
699 }
700 return ((const xmlChar *) *buf);
701}
702
703/**
704 * xmlSchemaFormatItemForReport:
705 * @buf: the string buffer
706 * @itemDes: the designation of the item
707 * @itemName: the name of the item
708 * @item: the item as an object
709 * @itemNode: the node of the item
710 * @local: the local name
711 * @parsing: if the function is used during the parse
712 *
713 * Returns a representation of the given item used
714 * for error reports.
715 *
716 * The following order is used to build the resulting
717 * designation if the arguments are not NULL:
718 * 1a. If itemDes not NULL -> itemDes
719 * 1b. If (itemDes not NULL) and (itemName not NULL)
720 * -> itemDes + itemName
721 * 2. If the preceding was NULL and (item not NULL) -> item
722 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
723 *
724 * If the itemNode is an attribute node, the name of the attribute
725 * will be appended to the result.
726 *
727 * Returns the formatted string and sets @buf to the resulting value.
728 */
729static xmlChar*
730xmlSchemaFormatItemForReport(xmlChar **buf,
731 const xmlChar *itemDes,
732 xmlSchemaTypePtr item,
733 xmlNodePtr itemNode,
734 int parsing)
735{
736 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000737 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000738
739 if (*buf != NULL) {
740 xmlFree(*buf);
741 *buf = NULL;
742 }
743
William M. Brack2f2a6632004-08-20 23:09:47 +0000744 if (itemDes != NULL) {
745 *buf = xmlStrdup(itemDes);
746 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000747 if (item->type == XML_SCHEMA_TYPE_BASIC) {
748 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
749 *buf = xmlStrdup(BAD_CAST "'anyType'");
750 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
751 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
752 else {
753 /* *buf = xmlStrdup(BAD_CAST "bi "); */
754 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
755 *buf = xmlStrdup(BAD_CAST "'");
756 *buf = xmlStrcat(*buf, item->name);
757 *buf = xmlStrcat(*buf, BAD_CAST "'");
758 }
759 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
760 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
761 *buf = xmlStrdup(xmlSchemaElemDesST);
762 *buf = xmlStrcat(*buf, BAD_CAST " '");
763 *buf = xmlStrcat(*buf, item->name);
764 *buf = xmlStrcat(*buf, BAD_CAST "'");
765 } else {
766 *buf = xmlStrdup(xmlSchemaElemDesST);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000767 /* Local types will get to name
768 *buf = xmlStrcat(*buf, BAD_CAST " ");
769 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000770 }
771 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
772 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
773 *buf = xmlStrdup(xmlSchemaElemDesCT);
774 *buf = xmlStrcat(*buf, BAD_CAST " '");
775 *buf = xmlStrcat(*buf, item->name);
776 *buf = xmlStrcat(*buf, BAD_CAST "'");
777 } else {
778 *buf = xmlStrdup(xmlSchemaElemDesCT);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000779 /* Local types will get to name
780 *buf = xmlStrcat(*buf, BAD_CAST " ");
781 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000782 }
783 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
784 xmlSchemaAttributePtr attr;
785
786 attr = (xmlSchemaAttributePtr) item;
787 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
788 (attr->ref == NULL)) {
789 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
790 *buf = xmlStrcat(*buf, BAD_CAST " '");
791 *buf = xmlStrcat(*buf, attr->name);
792 *buf = xmlStrcat(*buf, BAD_CAST "'");
793 } else {
794 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
795 *buf = xmlStrcat(*buf, BAD_CAST " '");
796 *buf = xmlStrcat(*buf, attr->refPrefix);
797 *buf = xmlStrcat(*buf, BAD_CAST ":");
798 *buf = xmlStrcat(*buf, attr->ref);
799 *buf = xmlStrcat(*buf, BAD_CAST "'");
800 }
801 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
802 xmlSchemaElementPtr elem;
803
804 elem = (xmlSchemaElementPtr) item;
805 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
806 (elem->ref == NULL)) {
807 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
808 *buf = xmlStrcat(*buf, BAD_CAST " '");
809 *buf = xmlStrcat(*buf, elem->name);
810 *buf = xmlStrcat(*buf, BAD_CAST "'");
811 } else {
812 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
813 *buf = xmlStrcat(*buf, BAD_CAST " '");
814 *buf = xmlStrcat(*buf, elem->refPrefix);
815 *buf = xmlStrcat(*buf, BAD_CAST ":");
816 *buf = xmlStrcat(*buf, elem->ref);
817 *buf = xmlStrcat(*buf, BAD_CAST "'");
818 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000819 } else
820 named = 0;
821 } else
822 named = 0;
823
824 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000825 xmlNodePtr elem;
826
827 if (itemNode->type == XML_ATTRIBUTE_NODE)
828 elem = itemNode->parent;
829 else
830 elem = itemNode;
831 *buf = xmlStrdup(BAD_CAST "Element '");
832 if (parsing)
833 *buf = xmlStrcat(*buf, elem->name);
834 else
835 *buf = xmlStrcat(*buf,
836 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
837 *buf = xmlStrcat(*buf, BAD_CAST "'");
838 }
839 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
840 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
841 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
842 itemNode->ns, itemNode->name));
843 *buf = xmlStrcat(*buf, BAD_CAST "'");
844 }
845 FREE_AND_NULL(str);
846
847 return (*buf);
848}
849
850/**
851 * xmlSchemaPFormatItemDes:
852 * @buf: the string buffer
853 * @item: the item as a schema object
854 * @itemNode: the item as a node
855 *
856 * If the pointer to @buf is not NULL and @but holds no value,
857 * the value is set to a item designation using
858 * xmlSchemaFormatItemForReport. This one avoids adding
859 * an attribute designation postfix.
860 *
861 * Returns a string of all enumeration elements.
862 */
863static void
864xmlSchemaPRequestItemDes(xmlChar **buf,
865 xmlSchemaTypePtr item,
866 xmlNodePtr itemNode)
867{
868 if ((buf == 0) || (*buf != NULL))
869 return;
870 if (itemNode->type == XML_ATTRIBUTE_NODE)
871 itemNode = itemNode->parent;
872 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
873}
874
875/**
876 * xmlSchemaFormatFacetEnumSet:
877 * @buf: the string buffer
878 * @type: the type holding the enumeration facets
879 *
880 * Builds a string consisting of all enumeration elements.
881 *
882 * Returns a string of all enumeration elements.
883 */
884static const xmlChar *
885xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
886{
887 xmlSchemaFacetLinkPtr link;
888
889 if (*buf != NULL)
890 xmlFree(*buf);
891 *buf = NULL;
892 for (link = type->facetSet; link != NULL; link = link->next) {
893 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
894 if (*buf == NULL) {
895 *buf = xmlStrdup(BAD_CAST "'");
896 *buf = xmlStrcat(*buf, link->facet->value);
897 *buf = xmlStrcat(*buf, BAD_CAST "'");
898 } else {
899 *buf = xmlStrcat(*buf, BAD_CAST ", '");
900 *buf = xmlStrcat(*buf, link->facet->value);
901 *buf = xmlStrcat(*buf, BAD_CAST "'");
902 }
903 }
904 }
905 return ((const xmlChar *) *buf);
906}
907
908/**
909 * xmlSchemaVFacetErr:
910 * @ctxt: the schema validation context
911 * @error: the error code
912 * @node: the node to be validated
913 * @value: the value of the node
914 * @type: the type holding the facet
915 * @facet: the facet
916 * @message: the error message of NULL
917 * @str1: extra data
918 * @str2: extra data
919 * @str3: extra data
920 *
921 * Reports a facet validation error.
922 * TODO: Should this report the value of an element as well?
923 */
924static void
925xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
926 xmlParserErrors error,
927 xmlNodePtr node,
928 const xmlChar *value,
929 unsigned long length,
930 xmlSchemaTypePtr type,
931 xmlSchemaFacetPtr facet,
932 const char *message,
933 const xmlChar *str1,
934 const xmlChar *str2,
935 const xmlChar *str3)
936{
937 xmlChar *str = NULL, *msg = NULL;
938 xmlSchemaTypeType facetType;
939
940 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
941 msg = xmlStrcat(msg, BAD_CAST " [");
942 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
943 msg = xmlStrcat(msg, BAD_CAST ", facet '");
944 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
945 facetType = XML_SCHEMA_FACET_ENUMERATION;
946 /*
947 * If enumerations are validated, one must not expect the
948 * facet to be given.
949 */
950 } else
951 facetType = facet->type;
952 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
953 msg = xmlStrcat(msg, BAD_CAST "']: ");
954 if (message == NULL) {
955 /*
956 * Use a default message.
957 */
958 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
959 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
960 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
961
962 char len[25], actLen[25];
963
964 /* FIXME, TODO: What is the max expected string length of the
965 * this value?
966 */
967 if (node->type == XML_ATTRIBUTE_NODE)
968 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
969 else
970 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
971
972 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
973 snprintf(actLen, 24, "%lu", length);
974
975 if (facetType == XML_SCHEMA_FACET_LENGTH)
976 msg = xmlStrcat(msg,
977 BAD_CAST "this differs from the allowed length of '%s'.\n");
978 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
979 msg = xmlStrcat(msg,
980 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
981 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
982 msg = xmlStrcat(msg,
983 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
984
985 if (node->type == XML_ATTRIBUTE_NODE)
986 xmlSchemaVErrExt(ctxt, node, error,
987 (const char *) msg,
988 value, (const xmlChar *) actLen, (const xmlChar *) len,
989 NULL, NULL);
990 else
991 xmlSchemaVErr(ctxt, node, error,
992 (const char *) msg,
993 (const xmlChar *) actLen, (const xmlChar *) len);
994
995 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
996 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
997 "of the set {%s}.\n");
998 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
999 xmlSchemaFormatFacetEnumSet(&str, type));
1000 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1001 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1002 "by the pattern '%s'.\n");
1003 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1004 facet->value);
1005 } else if (node->type == XML_ATTRIBUTE_NODE) {
1006 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1007 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1008 } else {
1009 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1010 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1011 }
1012 } else {
1013 msg = xmlStrcat(msg, (const xmlChar *) message);
1014 msg = xmlStrcat(msg, BAD_CAST ".\n");
1015 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1016 }
1017 FREE_AND_NULL(str)
1018 xmlFree(msg);
1019}
1020
1021/**
1022 * xmlSchemaVSimpleTypeErr:
1023 * @ctxt: the schema validation context
1024 * @error: the error code
1025 * @type: the type used for validation
1026 * @node: the node containing the validated value
1027 * @value: the validated value
1028 *
1029 * Reports a simple type validation error.
1030 * TODO: Should this report the value of an element as well?
1031 */
1032static void
1033xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1034 xmlParserErrors error,
1035 xmlNodePtr node,
1036 const xmlChar *value,
1037 xmlSchemaTypePtr type)
1038{
1039 xmlChar *str = NULL, *msg = NULL;
1040
1041 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1042 msg = xmlStrcat(msg, BAD_CAST " [");
1043 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1044 if (node->type == XML_ATTRIBUTE_NODE) {
1045 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1046 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1047 } else {
1048 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1049 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1050 }
1051 FREE_AND_NULL(str)
1052 xmlFree(msg);
1053}
1054
1055/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001056 * xmlSchemaVComplexTypeErr:
1057 * @ctxt: the schema validation context
1058 * @error: the error code
1059 * @node: the node containing the validated value
1060 * @type: the complex type used for validation
1061 * @message: the error message
1062 *
1063 * Reports a complex type validation error.
1064 */
1065static void
1066xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1067 xmlParserErrors error,
1068 xmlNodePtr node,
1069 xmlSchemaTypePtr type,
1070 const char *message)
1071{
1072 xmlChar *str = NULL, *msg = NULL;
1073
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001074 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001075 /* Specify the complex type only if it is global. */
1076 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001077 msg = xmlStrcat(msg, BAD_CAST " [");
1078 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1079 msg = xmlStrcat(msg, BAD_CAST "]");
1080 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001081 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1082 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001083 (const xmlChar *) message, NULL);
1084 FREE_AND_NULL(str)
1085 xmlFree(msg);
1086}
1087
1088/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001089 * xmlSchemaVComplexTypeElemErr:
1090 * @ctxt: the schema validation context
1091 * @error: the error code
1092 * @node: the node containing the validated value
1093 * @type: the complex type used for validation
1094 * @message: the error message
1095 *
1096 * Reports a complex type validation error.
1097 */
1098static void
1099xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1100 xmlParserErrors error,
1101 xmlNodePtr node,
1102 xmlSchemaTypePtr type,
1103 const char *message,
1104 int nbval,
1105 int nbneg,
1106 xmlChar **values)
1107{
1108 xmlChar *str = NULL, *msg = NULL;
1109 xmlChar *localName, *nsName;
1110 const xmlChar *cur, *end;
1111 int i;
1112
1113 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1114 /* Specify the complex type only if it is global. */
1115 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1116 msg = xmlStrcat(msg, BAD_CAST " [");
1117 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1118 msg = xmlStrcat(msg, BAD_CAST "]");
1119 FREE_AND_NULL(str)
1120 }
1121 msg = xmlStrcat(msg, BAD_CAST ": ");
1122 msg = xmlStrcat(msg, (const xmlChar *) message);
1123 /*
1124 * Note that is does not make sense to report that we have a
1125 * wildcard here, since the wildcard might be unfolded into
1126 * multiple transitions.
1127 */
1128 if (nbval + nbneg > 0) {
1129 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001130 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001131 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001132 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001133 nsName = NULL;
1134
1135 for (i = 0; i < nbval + nbneg; i++) {
1136 cur = values[i];
1137 /*
1138 * Get the local name.
1139 */
1140 localName = NULL;
1141
1142 end = cur;
1143 if (*end == '*') {
1144 localName = xmlStrdup(BAD_CAST "*");
1145 *end++;
1146 } else {
1147 while ((*end != 0) && (*end != '|'))
1148 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001149 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001150 }
1151 if (*end != 0) {
1152 *end++;
1153 /*
1154 * Skip "*|*" if they come with negated expressions, since
1155 * they represent the same negated wildcard.
1156 */
1157 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1158 /*
1159 * Get the namespace name.
1160 */
1161 cur = end;
1162 if (*end == '*') {
1163 nsName = xmlStrdup(BAD_CAST "{*}");
1164 } else {
1165 while (*end != 0)
1166 end++;
1167
1168 if (i >= nbval)
1169 nsName = xmlStrdup(BAD_CAST "{##other:");
1170 else
1171 nsName = xmlStrdup(BAD_CAST "{");
1172
1173 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1174 nsName = xmlStrcat(nsName, BAD_CAST "}");
1175 }
1176 str = xmlStrcat(str, BAD_CAST nsName);
1177 FREE_AND_NULL(nsName)
1178 } else {
1179 FREE_AND_NULL(localName);
1180 continue;
1181 }
1182 }
1183 str = xmlStrcat(str, BAD_CAST localName);
1184 FREE_AND_NULL(localName);
1185
1186 if (i < nbval + nbneg -1)
1187 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001188 }
1189 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001190 msg = xmlStrcat(msg, BAD_CAST str);
1191 FREE_AND_NULL(str)
1192 }
1193 msg = xmlStrcat(msg, BAD_CAST ".\n");
1194 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1195 xmlFree(msg);
1196}
1197
1198/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001199 * xmlSchemaPMissingAttrErr:
1200 * @ctxt: the schema validation context
1201 * @ownerDes: the designation of the owner
1202 * @ownerName: the name of the owner
1203 * @ownerItem: the owner as a schema object
1204 * @ownerElem: the owner as an element node
1205 * @node: the parent element node of the missing attribute node
1206 * @type: the corresponding type of the attribute node
1207 *
1208 * Reports an illegal attribute.
1209 */
1210static void
1211xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1212 xmlParserErrors error,
1213 xmlChar **ownerDes,
1214 xmlSchemaTypePtr ownerItem,
1215 xmlNodePtr ownerElem,
1216 const char *name,
1217 const char *message)
1218{
1219 xmlChar *des = NULL;
1220
1221 if (ownerDes == NULL)
1222 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1223 else if (*ownerDes == NULL) {
1224 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1225 des = *ownerDes;
1226 } else
1227 des = *ownerDes;
1228 if (message != NULL)
1229 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1230 else
1231 xmlSchemaPErr(ctxt, ownerElem, error,
1232 "%s: The attribute '%s' is required but missing.\n",
1233 BAD_CAST des, BAD_CAST name);
1234 if (ownerDes == NULL)
1235 FREE_AND_NULL(des);
1236}
1237
William M. Brack2f2a6632004-08-20 23:09:47 +00001238/**
1239 * xmlSchemaCompTypeToString:
1240 * @type: the type of the schema item
1241 *
1242 * Returns the component name of a schema item.
1243 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001244static const char *
1245xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1246{
1247 switch (type) {
1248 case XML_SCHEMA_TYPE_SIMPLE:
1249 return("simple type definition");
1250 case XML_SCHEMA_TYPE_COMPLEX:
1251 return("complex type definition");
1252 case XML_SCHEMA_TYPE_ELEMENT:
1253 return("element declaration");
1254 case XML_SCHEMA_TYPE_ATTRIBUTE:
1255 return("attribute declaration");
1256 case XML_SCHEMA_TYPE_GROUP:
1257 return("model group definition");
1258 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1259 return("attribute group definition");
1260 case XML_SCHEMA_TYPE_NOTATION:
1261 return("notation declaration");
1262 default:
1263 return("Not a schema component");
1264 }
1265}
1266/**
1267 * xmlSchemaPResCompAttrErr:
1268 * @ctxt: the schema validation context
1269 * @error: the error code
1270 * @ownerDes: the designation of the owner
1271 * @ownerItem: the owner as a schema object
1272 * @ownerElem: the owner as an element node
1273 * @name: the name of the attribute holding the QName
1274 * @refName: the referenced local name
1275 * @refURI: the referenced namespace URI
1276 * @message: optional message
1277 *
1278 * Used to report QName attribute values that failed to resolve
1279 * to schema components.
1280 */
1281static void
1282xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1283 xmlParserErrors error,
1284 xmlChar **ownerDes,
1285 xmlSchemaTypePtr ownerItem,
1286 xmlNodePtr ownerElem,
1287 const char *name,
1288 const xmlChar *refName,
1289 const xmlChar *refURI,
1290 xmlSchemaTypeType refType,
1291 const char *refTypeStr)
1292{
1293 xmlChar *des = NULL, *strA = NULL;
1294
1295 if (ownerDes == NULL)
1296 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1297 else if (*ownerDes == NULL) {
1298 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1299 des = *ownerDes;
1300 } else
1301 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001302 if (refTypeStr == NULL)
1303 refTypeStr = xmlSchemaCompTypeToString(refType);
1304 xmlSchemaPErrExt(ctxt, ownerElem, error,
1305 NULL, NULL, NULL,
1306 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1307 "%s.\n", BAD_CAST des, BAD_CAST name,
1308 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1309 BAD_CAST refTypeStr, NULL);
1310 if (ownerDes == NULL)
1311 FREE_AND_NULL(des)
1312 FREE_AND_NULL(strA)
1313}
1314
William M. Brack2f2a6632004-08-20 23:09:47 +00001315/**
1316 * xmlSchemaPCustomAttrErr:
1317 * @ctxt: the schema parser context
1318 * @error: the error code
1319 * @ownerDes: the designation of the owner
1320 * @ownerItem: the owner as a schema object
1321 * @attr: the illegal attribute node
1322 *
1323 * Reports an illegal attribute during the parse.
1324 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001325static void
1326xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001327 xmlParserErrors error,
1328 xmlChar **ownerDes,
1329 xmlSchemaTypePtr ownerItem,
1330 xmlAttrPtr attr,
1331 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001332{
1333 xmlChar *des = NULL;
1334
1335 if (ownerDes == NULL)
1336 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1337 else if (*ownerDes == NULL) {
1338 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1339 des = *ownerDes;
1340 } else
1341 des = *ownerDes;
1342 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1343 "%s, attribute '%s': %s.\n",
1344 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1345 if (ownerDes == NULL)
1346 FREE_AND_NULL(des);
1347}
1348
1349/**
1350 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001351 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001352 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001353 * @ownerDes: the designation of the attribute's owner
1354 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001355 * @attr: the illegal attribute node
1356 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001357 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001358 */
1359static void
1360xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1361 xmlParserErrors error,
1362 xmlChar **ownerDes,
1363 xmlSchemaTypePtr ownerItem,
1364 xmlAttrPtr attr)
1365{
1366 xmlChar *des = NULL, *strA = NULL;
1367
1368 if (ownerDes == NULL)
1369 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1370 else if (*ownerDes == NULL) {
1371 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1372 des = *ownerDes;
1373 } else
1374 des = *ownerDes;
1375 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1376 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1377 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1378 if (ownerDes == NULL)
1379 FREE_AND_NULL(des);
1380 FREE_AND_NULL(strA);
1381}
1382
William M. Brack2f2a6632004-08-20 23:09:47 +00001383/**
1384 * xmlSchemaPAquireDes:
1385 * @des: the first designation
1386 * @itemDes: the second designation
1387 * @item: the schema item
1388 * @itemElem: the node of the schema item
1389 *
1390 * Creates a designation for an item.
1391 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001392static void
1393xmlSchemaPAquireDes(xmlChar **des,
1394 xmlChar **itemDes,
1395 xmlSchemaTypePtr item,
1396 xmlNodePtr itemElem)
1397{
1398 if (itemDes == NULL)
1399 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1400 else if (*itemDes == NULL) {
1401 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1402 *des = *itemDes;
1403 } else
1404 *des = *itemDes;
1405}
1406
William M. Brack2f2a6632004-08-20 23:09:47 +00001407/**
1408 * xmlSchemaPCustomErr:
1409 * @ctxt: the schema parser context
1410 * @error: the error code
1411 * @itemDes: the designation of the schema item
1412 * @item: the schema item
1413 * @itemElem: the node of the schema item
1414 * @message: the error message
1415 * @str1: an optional param for the error message
1416 * @str2: an optional param for the error message
1417 * @str3: an optional param for the error message
1418 *
1419 * Reports an error during parsing.
1420 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001421static void
1422xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1423 xmlParserErrors error,
1424 xmlChar **itemDes,
1425 xmlSchemaTypePtr item,
1426 xmlNodePtr itemElem,
1427 const char *message,
1428 const xmlChar *str1,
1429 const xmlChar *str2,
1430 const xmlChar *str3)
1431{
1432 xmlChar *des = NULL, *msg = NULL;
1433
1434 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1435 msg = xmlStrdup(BAD_CAST "%s: ");
1436 msg = xmlStrcat(msg, (const xmlChar *) message);
1437 msg = xmlStrcat(msg, BAD_CAST ".\n");
1438 if ((itemElem == NULL) && (item != NULL))
1439 itemElem = item->node;
1440 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1441 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1442 if (itemDes == NULL)
1443 FREE_AND_NULL(des);
1444 FREE_AND_NULL(msg);
1445}
1446
William M. Brack2f2a6632004-08-20 23:09:47 +00001447/**
1448 * xmlSchemaPCustomErr:
1449 * @ctxt: the schema parser context
1450 * @error: the error code
1451 * @itemDes: the designation of the schema item
1452 * @item: the schema item
1453 * @itemElem: the node of the schema item
1454 * @message: the error message
1455 * @str1: the optional param for the error message
1456 *
1457 * Reports an error during parsing.
1458 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001459static void
1460xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1461 xmlParserErrors error,
1462 xmlChar **itemDes,
1463 xmlSchemaTypePtr item,
1464 xmlNodePtr itemElem,
1465 const char *message,
1466 const xmlChar *str1)
1467{
1468 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1469 str1, NULL, NULL);
1470}
1471
William M. Brack2f2a6632004-08-20 23:09:47 +00001472/**
1473 * xmlSchemaPAttrUseErr:
1474 * @ctxt: the schema parser context
1475 * @error: the error code
1476 * @itemDes: the designation of the schema type
1477 * @item: the schema type
1478 * @itemElem: the node of the schema type
1479 * @attr: the invalid schema attribute
1480 * @message: the error message
1481 * @str1: the optional param for the error message
1482 *
1483 * Reports an attribute use error during parsing.
1484 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001485static void
1486xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1487 xmlParserErrors error,
1488 xmlChar **itemDes,
1489 xmlSchemaTypePtr item,
1490 xmlNodePtr itemElem,
1491 const xmlSchemaAttributePtr attr,
1492 const char *message,
1493 const xmlChar *str1)
1494{
1495 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1496
1497 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1498 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1499 xmlSchemaGetAttrName(attr));
1500 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1501 msg = xmlStrcat(msg, (const xmlChar *) message);
1502 msg = xmlStrcat(msg, BAD_CAST ".\n");
1503 if ((itemElem == NULL) && (item != NULL))
1504 itemElem = item->node;
1505 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1506 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1507 if (itemDes == NULL)
1508 FREE_AND_NULL(des);
1509 FREE_AND_NULL(strA);
1510 xmlFree(msg);
1511}
1512
William M. Brack2f2a6632004-08-20 23:09:47 +00001513/**
1514 * xmlSchemaPIllegalFacetAtomicErr:
1515 * @ctxt: the schema parser context
1516 * @error: the error code
1517 * @itemDes: the designation of the type
1518 * @item: the schema type
1519 * @baseItem: the base type of type
1520 * @facet: the illegal facet
1521 *
1522 * Reports an illegal facet for atomic simple types.
1523 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001524static void
1525xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1526 xmlParserErrors error,
1527 xmlChar **itemDes,
1528 xmlSchemaTypePtr item,
1529 xmlSchemaTypePtr baseItem,
1530 xmlSchemaFacetPtr facet)
1531{
1532 xmlChar *des = NULL, *strT = NULL;
1533
1534 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1535 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1536 "%s: The facet '%s' is not allowed on types derived from the "
1537 "type %s.\n",
1538 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1539 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1540 NULL, NULL);
1541 if (itemDes == NULL)
1542 FREE_AND_NULL(des);
1543 FREE_AND_NULL(strT);
1544}
1545
William M. Brack2f2a6632004-08-20 23:09:47 +00001546/**
1547 * xmlSchemaPIllegalFacetListUnionErr:
1548 * @ctxt: the schema parser context
1549 * @error: the error code
1550 * @itemDes: the designation of the schema item involved
1551 * @item: the schema item involved
1552 * @facet: the illegal facet
1553 *
1554 * Reports an illegal facet for <list> and <union>.
1555 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001556static void
1557xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1558 xmlParserErrors error,
1559 xmlChar **itemDes,
1560 xmlSchemaTypePtr item,
1561 xmlSchemaFacetPtr facet)
1562{
1563 xmlChar *des = NULL, *strT = NULL;
1564
1565 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1566 xmlSchemaPErr(ctxt, item->node, error,
1567 "%s: The facet '%s' is not allowed.\n",
1568 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1569 if (itemDes == NULL)
1570 FREE_AND_NULL(des);
1571 FREE_AND_NULL(strT);
1572}
1573
1574/**
1575 * xmlSchemaPMutualExclAttrErr:
1576 * @ctxt: the schema validation context
1577 * @error: the error code
1578 * @elemDes: the designation of the parent element node
1579 * @attr: the bad attribute node
1580 * @type: the corresponding type of the attribute node
1581 *
1582 * Reports an illegal attribute.
1583 */
1584static void
1585xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1586 xmlParserErrors error,
1587 xmlChar **ownerDes,
1588 xmlSchemaTypePtr ownerItem,
1589 xmlAttrPtr attr,
1590 const char *name1,
1591 const char *name2)
1592{
1593 xmlChar *des = NULL;
1594
1595 if (ownerDes == NULL)
1596 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1597 else if (*ownerDes == NULL) {
1598 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1599 des = *ownerDes;
1600 } else
1601 des = *ownerDes;
1602 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1603 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1604 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1605 if (ownerDes == NULL)
1606 FREE_AND_NULL(des)
1607}
1608
1609/**
1610 * xmlSchemaPSimpleTypeErr:
1611 * @ctxt: the schema validation context
1612 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001613 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001614 * @ownerDes: the designation of the owner
1615 * @ownerItem: the schema object if existent
1616 * @node: the validated node
1617 * @value: the validated value
1618 *
1619 * Reports a simple type validation error.
1620 * TODO: Should this report the value of an element as well?
1621 */
1622static void
1623xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1624 xmlParserErrors error,
1625 xmlChar **ownerDes,
1626 xmlSchemaTypePtr ownerItem,
1627 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001628 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001629 const char *typeDes,
1630 const xmlChar *value,
1631 const char *message,
1632 const xmlChar *str1,
1633 const xmlChar *str2)
1634{
William M. Brack2f2a6632004-08-20 23:09:47 +00001635 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001636
1637 if (ownerDes == NULL)
1638 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1639 else if (*ownerDes == NULL) {
1640 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1641 des = *ownerDes;
1642 } else
1643 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001644 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001645 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001646 if (message == NULL) {
1647 /*
1648 * Use default messages.
1649 */
1650 if (node->type == XML_ATTRIBUTE_NODE) {
1651 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1652 "%s, attribute '%s' [%s]: The value '%s' is not "
1653 "valid.\n",
1654 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1655 node->name), BAD_CAST typeDes, value, NULL);
1656 } else {
1657 xmlSchemaPErr(ctxt, node, error,
1658 "%s [%s]: The character content is not valid.\n",
1659 BAD_CAST des, BAD_CAST typeDes);
1660 }
1661 } else {
1662 xmlChar *msg;
1663
1664 msg = xmlStrdup(BAD_CAST "%s");
1665 if (node->type == XML_ATTRIBUTE_NODE)
1666 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1667 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1668 msg = xmlStrcat(msg, (const xmlChar *) message);
1669 msg = xmlStrcat(msg, BAD_CAST ".\n");
1670 if (node->type == XML_ATTRIBUTE_NODE) {
1671 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1672 (const char *) msg,
1673 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1674 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1675 } else {
1676 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1677 (const char *) msg,
1678 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1679 }
1680 xmlFree(msg);
1681 }
1682 /* Cleanup. */
1683 FREE_AND_NULL(strA)
1684 FREE_AND_NULL(strT)
1685 if (ownerDes == NULL)
1686 FREE_AND_NULL(des)
1687}
1688
William M. Brack2f2a6632004-08-20 23:09:47 +00001689/**
1690 * xmlSchemaPContentErr:
1691 * @ctxt: the schema parser context
1692 * @error: the error code
1693 * @onwerDes: the designation of the holder of the content
1694 * @ownerItem: the owner item of the holder of the content
1695 * @ownerElem: the node of the holder of the content
1696 * @child: the invalid child node
1697 * @message: the optional error message
1698 * @content: the optional string describing the correct content
1699 *
1700 * Reports an error concerning the content of a schema element.
1701 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001702static void
1703xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1704 xmlParserErrors error,
1705 xmlChar **ownerDes,
1706 xmlSchemaTypePtr ownerItem,
1707 xmlNodePtr ownerElem,
1708 xmlNodePtr child,
1709 const char *message,
1710 const char *content)
1711{
1712 xmlChar *des = NULL;
1713
1714 if (ownerDes == NULL)
1715 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1716 else if (*ownerDes == NULL) {
1717 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1718 des = *ownerDes;
1719 } else
1720 des = *ownerDes;
1721 if (message != NULL)
1722 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1723 "%s: %s.\n",
1724 BAD_CAST des, BAD_CAST message);
1725 else {
1726 if (content != NULL) {
1727 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1728 "%s: The content is not valid. Expected is %s.\n",
1729 BAD_CAST des, BAD_CAST content);
1730 } else {
1731 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1732 "%s: The content is not valid.\n",
1733 BAD_CAST des, NULL);
1734 }
1735 }
1736 if (ownerDes == NULL)
1737 FREE_AND_NULL(des)
1738}
1739
1740/**
1741 * xmlSchemaVIllegalAttrErr:
1742 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001743 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001744 * @attr: the illegal attribute node
1745 *
1746 * Reports an illegal attribute.
1747 */
1748static void
1749xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001750 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001751 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001752{
1753 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001754
1755 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1756 error,
1757 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001758 "%s: The attribute '%s' is not allowed.\n",
1759 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1760 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1761 FREE_AND_NULL(strE)
1762 FREE_AND_NULL(strA)
1763}
1764
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001765
1766static int
1767xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1768{
1769 switch (item->type) {
1770 case XML_SCHEMA_TYPE_COMPLEX:
1771 case XML_SCHEMA_TYPE_SIMPLE:
1772 case XML_SCHEMA_TYPE_GROUP:
1773 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1774 return(1);
1775 break;
1776 case XML_SCHEMA_TYPE_ELEMENT:
1777 if ( ((xmlSchemaElementPtr) item)->flags &
1778 XML_SCHEMAS_ELEM_GLOBAL)
1779 return(1);
1780 break;
1781 case XML_SCHEMA_TYPE_ATTRIBUTE:
1782 if ( ((xmlSchemaAttributePtr) item)->flags &
1783 XML_SCHEMAS_ATTR_GLOBAL)
1784 return(1);
1785 break;
1786 /* Note that attribute groups are always global. */
1787 default:
1788 return(1);
1789 }
1790 return (0);
1791}
1792
William M. Brack2f2a6632004-08-20 23:09:47 +00001793/**
1794 * xmlSchemaVCustomErr:
1795 * @ctxt: the schema validation context
1796 * @error: the error code
1797 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001798 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001799 * @message: the error message
1800 * @str1: the optional param for the message
1801 *
1802 * Reports a validation error.
1803 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001804static void
1805xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1806 xmlParserErrors error,
1807 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001808 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001809 const char *message,
1810 const xmlChar *str1)
1811{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001812 xmlChar *msg = NULL, *str = NULL;
1813
1814 if (node == NULL) {
1815 xmlSchemaVErr(ctxt, NULL,
1816 XML_SCHEMAV_INTERNAL,
1817 "Internal error: xmlSchemaVCustomErr, no node "
1818 "given.\n", NULL, NULL);
1819 return;
1820 }
1821 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1822 if (node->type != XML_DOCUMENT_NODE) {
1823 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001824 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001825 msg = xmlStrcat(msg, BAD_CAST " [");
1826 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1827 msg = xmlStrcat(msg, BAD_CAST "]");
1828 }
1829 msg = xmlStrcat(msg, BAD_CAST ": ");
1830 } else
1831 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001832 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001833 msg = xmlStrcat(msg, BAD_CAST ".\n");
1834 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1835 FREE_AND_NULL(msg)
1836 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837}
1838
William M. Brack2f2a6632004-08-20 23:09:47 +00001839/**
1840 * xmlSchemaWildcardPCToString:
1841 * @pc: the type of processContents
1842 *
1843 * Returns a string representation of the type of
1844 * processContents.
1845 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001846static const char *
1847xmlSchemaWildcardPCToString(int pc)
1848{
1849 switch (pc) {
1850 case XML_SCHEMAS_ANY_SKIP:
1851 return ("skip");
1852 case XML_SCHEMAS_ANY_LAX:
1853 return ("lax");
1854 case XML_SCHEMAS_ANY_STRICT:
1855 return ("strict");
1856 default:
1857 return ("invalid process contents");
1858 }
1859}
1860
William M. Brack2f2a6632004-08-20 23:09:47 +00001861/**
1862 * xmlSchemaVWildcardErr:
1863 * @ctxt: the schema validation context
1864 * @error: the error code
1865 * @node: the validated node
1866 * @wild: the wildcard used
1867 * @message: the error message
1868 *
1869 * Reports an validation-by-wildcard error.
1870 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001871static void
1872xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1873 xmlParserErrors error,
1874 xmlNodePtr node,
1875 xmlSchemaWildcardPtr wild,
1876 const char *message)
1877{
1878 xmlChar *des = NULL, *msg = NULL;
1879
1880 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1881 msg = xmlStrdup(BAD_CAST "%s, [");
1882 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001883 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001884 msg = xmlStrcat(msg, (const xmlChar *) message);
1885 msg = xmlStrcat(msg, BAD_CAST ".\n");
1886 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1887 FREE_AND_NULL(des);
1888 FREE_AND_NULL(msg);
1889}
1890
1891/**
1892 * xmlSchemaVMissingAttrErr:
1893 * @ctxt: the schema validation context
1894 * @node: the parent element node of the missing attribute node
1895 * @type: the corresponding type of the attribute node
1896 *
1897 * Reports an illegal attribute.
1898 */
1899static void
1900xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1901 xmlNodePtr elem,
1902 xmlSchemaAttributePtr type)
1903{
1904 const xmlChar *name, *uri;
1905 xmlChar *strE = NULL, *strA = NULL;
1906
1907 if (type->ref != NULL) {
1908 name = type->ref;
1909 uri = type->refNs;
1910 } else {
1911 name = type->name;
1912 uri = type->targetNamespace;
1913 }
1914 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001915 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1916 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001917 "%s: The attribute %s is required but missing.\n",
1918 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1919 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1920 FREE_AND_NULL(strE)
1921 FREE_AND_NULL(strA)
1922}
1923
Daniel Veillard4255d502002-04-16 15:50:10 +00001924/************************************************************************
1925 * *
1926 * Allocation functions *
1927 * *
1928 ************************************************************************/
1929
1930/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001931 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001932 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001933 *
1934 * Allocate a new Schema structure.
1935 *
1936 * Returns the newly allocated structure or NULL in case or error
1937 */
1938static xmlSchemaPtr
1939xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1940{
1941 xmlSchemaPtr ret;
1942
1943 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1944 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001945 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001946 return (NULL);
1947 }
1948 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001949 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001950 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001951
1952 return (ret);
1953}
1954
1955/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001956 * xmlSchemaNewSchema:
1957 * @ctxt: a schema validation context
1958 *
1959 * Allocate a new Schema structure.
1960 *
1961 * Returns the newly allocated structure or NULL in case or error
1962 */
1963static xmlSchemaAssemblePtr
1964xmlSchemaNewAssemble(void)
1965{
1966 xmlSchemaAssemblePtr ret;
1967
1968 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1969 if (ret == NULL) {
1970 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1971 return (NULL);
1972 }
1973 memset(ret, 0, sizeof(xmlSchemaAssemble));
1974 ret->items = NULL;
1975 return (ret);
1976}
1977
1978/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001979 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001980 *
1981 * Allocate a new Facet structure.
1982 *
1983 * Returns the newly allocated structure or NULL in case or error
1984 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001985xmlSchemaFacetPtr
1986xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001987{
1988 xmlSchemaFacetPtr ret;
1989
1990 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1991 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001992 return (NULL);
1993 }
1994 memset(ret, 0, sizeof(xmlSchemaFacet));
1995
1996 return (ret);
1997}
1998
1999/**
2000 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002001 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002002 * @node: a node
2003 *
2004 * Allocate a new annotation structure.
2005 *
2006 * Returns the newly allocated structure or NULL in case or error
2007 */
2008static xmlSchemaAnnotPtr
2009xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2010{
2011 xmlSchemaAnnotPtr ret;
2012
2013 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2014 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002015 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002016 return (NULL);
2017 }
2018 memset(ret, 0, sizeof(xmlSchemaAnnot));
2019 ret->content = node;
2020 return (ret);
2021}
2022
2023/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002024 * xmlSchemaFreeAnnot:
2025 * @annot: a schema type structure
2026 *
2027 * Deallocate a annotation structure
2028 */
2029static void
2030xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2031{
2032 if (annot == NULL)
2033 return;
2034 xmlFree(annot);
2035}
2036
2037/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002038 * xmlSchemaFreeImport:
2039 * @import: a schema import structure
2040 *
2041 * Deallocate an import structure
2042 */
2043static void
2044xmlSchemaFreeImport(xmlSchemaImportPtr import)
2045{
2046 if (import == NULL)
2047 return;
2048
2049 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002050 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002051 xmlFree(import);
2052}
2053
2054/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002055 * xmlSchemaFreeInclude:
2056 * @include: a schema include structure
2057 *
2058 * Deallocate an include structure
2059 */
2060static void
2061xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2062{
2063 if (include == NULL)
2064 return;
2065
2066 xmlFreeDoc(include->doc);
2067 xmlFree(include);
2068}
2069
2070/**
2071 * xmlSchemaFreeIncludeList:
2072 * @includes: a schema include list
2073 *
2074 * Deallocate an include structure
2075 */
2076static void
2077xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2078{
2079 xmlSchemaIncludePtr next;
2080
2081 while (includes != NULL) {
2082 next = includes->next;
2083 xmlSchemaFreeInclude(includes);
2084 includes = next;
2085 }
2086}
2087
2088/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 * xmlSchemaFreeNotation:
2090 * @schema: a schema notation structure
2091 *
2092 * Deallocate a Schema Notation structure.
2093 */
2094static void
2095xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2096{
2097 if (nota == NULL)
2098 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002099 xmlFree(nota);
2100}
2101
2102/**
2103 * xmlSchemaFreeAttribute:
2104 * @schema: a schema attribute structure
2105 *
2106 * Deallocate a Schema Attribute structure.
2107 */
2108static void
2109xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2110{
2111 if (attr == NULL)
2112 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002113 if (attr->annot != NULL)
2114 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002115 if (attr->defVal != NULL)
2116 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002117 xmlFree(attr);
2118}
2119
2120/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002121 * xmlSchemaFreeWildcardNsSet:
2122 * set: a schema wildcard namespace
2123 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002124 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002125 */
2126static void
2127xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2128{
2129 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002130
Daniel Veillard3646d642004-06-02 19:19:14 +00002131 while (set != NULL) {
2132 next = set->next;
2133 xmlFree(set);
2134 set = next;
2135 }
2136}
2137
2138/**
2139 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002140 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002141 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002142 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002143 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002144void
Daniel Veillard3646d642004-06-02 19:19:14 +00002145xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2146{
2147 if (wildcard == NULL)
2148 return;
2149 if (wildcard->annot != NULL)
2150 xmlSchemaFreeAnnot(wildcard->annot);
2151 if (wildcard->nsSet != NULL)
2152 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2153 if (wildcard->negNsSet != NULL)
2154 xmlFree(wildcard->negNsSet);
2155 xmlFree(wildcard);
2156}
2157
2158/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 * xmlSchemaFreeAttributeGroup:
2160 * @schema: a schema attribute group structure
2161 *
2162 * Deallocate a Schema Attribute Group structure.
2163 */
2164static void
2165xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2166{
2167 if (attr == NULL)
2168 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002169 if (attr->annot != NULL)
2170 xmlSchemaFreeAnnot(attr->annot);
2171 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2172 (attr->attributeWildcard != NULL))
2173 xmlSchemaFreeWildcard(attr->attributeWildcard);
2174
Daniel Veillard4255d502002-04-16 15:50:10 +00002175 xmlFree(attr);
2176}
2177
2178/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002179 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002180 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002181 *
2182 * Deallocate a list of schema attribute uses.
2183 */
2184static void
2185xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2186{
2187 xmlSchemaAttributeLinkPtr next;
2188
2189 while (attrUse != NULL) {
2190 next = attrUse->next;
2191 xmlFree(attrUse);
2192 attrUse = next;
2193 }
2194}
2195
2196/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002197 * xmlSchemaFreeTypeLinkList:
2198 * @alink: a type link
2199 *
2200 * Deallocate a list of types.
2201 */
2202static void
2203xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2204{
2205 xmlSchemaTypeLinkPtr next;
2206
2207 while (link != NULL) {
2208 next = link->next;
2209 xmlFree(link);
2210 link = next;
2211 }
2212}
2213
2214/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002215 * xmlSchemaFreeElement:
2216 * @schema: a schema element structure
2217 *
2218 * Deallocate a Schema Element structure.
2219 */
2220static void
2221xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2222{
2223 if (elem == NULL)
2224 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002225 if (elem->annot != NULL)
2226 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002227 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002229 if (elem->defVal != NULL)
2230 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002231 xmlFree(elem);
2232}
2233
2234/**
2235 * xmlSchemaFreeFacet:
2236 * @facet: a schema facet structure
2237 *
2238 * Deallocate a Schema Facet structure.
2239 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002240void
Daniel Veillard4255d502002-04-16 15:50:10 +00002241xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2242{
2243 if (facet == NULL)
2244 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002245 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002246 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002247 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002249 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002250 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 xmlFree(facet);
2252}
2253
2254/**
2255 * xmlSchemaFreeType:
2256 * @type: a schema type structure
2257 *
2258 * Deallocate a Schema Type structure.
2259 */
2260void
2261xmlSchemaFreeType(xmlSchemaTypePtr type)
2262{
2263 if (type == NULL)
2264 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002265 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002266 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002267 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002268 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002269
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002270 facet = type->facets;
2271 while (facet != NULL) {
2272 next = facet->next;
2273 xmlSchemaFreeFacet(facet);
2274 facet = next;
2275 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002276 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002277 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2278 if (type->attributeUses != NULL)
2279 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002280 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002281 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002282 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2283 /*
2284 * NOTE: The only case where an attribute wildcard
2285 * is not owned, is if a complex type inherits it
2286 * from a base type.
2287 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002288 xmlSchemaFreeWildcard(type->attributeWildcard);
2289 }
2290 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002291 if (type->memberTypes != NULL)
2292 xmlSchemaFreeTypeLinkList(type->memberTypes);
2293 if (type->facetSet != NULL) {
2294 xmlSchemaFacetLinkPtr next, link;
2295
2296 link = type->facetSet;
2297 do {
2298 next = link->next;
2299 xmlFree(link);
2300 link = next;
2301 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002302 }
2303 if (type->contModel != NULL)
2304 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002305 xmlFree(type);
2306}
2307
2308/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002309 * xmlSchemaFreeTypeList:
2310 * @type: a schema type structure
2311 *
2312 * Deallocate a Schema Type structure.
2313 */
2314static void
2315xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2316{
2317 xmlSchemaTypePtr next;
2318
2319 while (type != NULL) {
2320 next = type->redef;
2321 xmlSchemaFreeType(type);
2322 type = next;
2323 }
2324}
2325
2326/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002327 * xmlSchemaFree:
2328 * @schema: a schema structure
2329 *
2330 * Deallocate a Schema structure.
2331 */
2332void
2333xmlSchemaFree(xmlSchemaPtr schema)
2334{
2335 if (schema == NULL)
2336 return;
2337
Daniel Veillard4255d502002-04-16 15:50:10 +00002338 if (schema->notaDecl != NULL)
2339 xmlHashFree(schema->notaDecl,
2340 (xmlHashDeallocator) xmlSchemaFreeNotation);
2341 if (schema->attrDecl != NULL)
2342 xmlHashFree(schema->attrDecl,
2343 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2344 if (schema->attrgrpDecl != NULL)
2345 xmlHashFree(schema->attrgrpDecl,
2346 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2347 if (schema->elemDecl != NULL)
2348 xmlHashFree(schema->elemDecl,
2349 (xmlHashDeallocator) xmlSchemaFreeElement);
2350 if (schema->typeDecl != NULL)
2351 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002352 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002353 if (schema->groupDecl != NULL)
2354 xmlHashFree(schema->groupDecl,
2355 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002356 if (schema->schemasImports != NULL)
2357 xmlHashFree(schema->schemasImports,
2358 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002359 if (schema->includes != NULL) {
2360 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2361 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002362 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002363 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002364 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002365 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002366 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002367 xmlFree(schema);
2368}
2369
2370/************************************************************************
2371 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002372 * Debug functions *
2373 * *
2374 ************************************************************************/
2375
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002376#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002377
Daniel Veillard4255d502002-04-16 15:50:10 +00002378/**
2379 * xmlSchemaElementDump:
2380 * @elem: an element
2381 * @output: the file output
2382 *
2383 * Dump the element
2384 */
2385static void
2386xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002387 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002388 const xmlChar * namespace ATTRIBUTE_UNUSED,
2389 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002390{
2391 if (elem == NULL)
2392 return;
2393
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002394 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2395 fprintf(output, "Particle: %s", name);
2396 fprintf(output, ", term element: %s", elem->ref);
2397 if (elem->refNs != NULL)
2398 fprintf(output, " ns %s", elem->refNs);
2399 } else {
2400 fprintf(output, "Element");
2401 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2402 fprintf(output, " (global)");
2403 fprintf(output, ": %s ", elem->name);
2404 if (namespace != NULL)
2405 fprintf(output, "ns %s", namespace);
2406 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002407 fprintf(output, "\n");
2408 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002409 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002410 if (elem->maxOccurs >= UNBOUNDED)
2411 fprintf(output, "max: unbounded\n");
2412 else if (elem->maxOccurs != 1)
2413 fprintf(output, "max: %d\n", elem->maxOccurs);
2414 else
2415 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002416 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002417 /*
2418 * Misc other properties.
2419 */
2420 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2421 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2422 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2423 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2424 (elem->id != NULL)) {
2425 fprintf(output, " props: ");
2426 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2427 fprintf(output, "[fixed] ");
2428 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2429 fprintf(output, "[default] ");
2430 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2431 fprintf(output, "[abstract] ");
2432 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2433 fprintf(output, "[nillable] ");
2434 if (elem->id != NULL)
2435 fprintf(output, "[id: '%s'] ", elem->id);
2436 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002437 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002438 /*
2439 * Default/fixed value.
2440 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002441 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002442 fprintf(output, " value: '%s'\n", elem->value);
2443 /*
2444 * Type.
2445 */
2446 if (elem->namedType != NULL) {
2447 fprintf(output, " type: %s ", elem->namedType);
2448 if (elem->namedTypeNs != NULL)
2449 fprintf(output, "ns %s\n", elem->namedTypeNs);
2450 else
2451 fprintf(output, "\n");
2452 }
2453 /*
2454 * Substitution group.
2455 */
2456 if (elem->substGroup != NULL) {
2457 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2458 if (elem->substGroupNs != NULL)
2459 fprintf(output, "ns %s\n", elem->substGroupNs);
2460 else
2461 fprintf(output, "\n");
2462 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002463}
2464
2465/**
2466 * xmlSchemaAnnotDump:
2467 * @output: the file output
2468 * @annot: a annotation
2469 *
2470 * Dump the annotation
2471 */
2472static void
2473xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2474{
2475 xmlChar *content;
2476
2477 if (annot == NULL)
2478 return;
2479
2480 content = xmlNodeGetContent(annot->content);
2481 if (content != NULL) {
2482 fprintf(output, " Annot: %s\n", content);
2483 xmlFree(content);
2484 } else
2485 fprintf(output, " Annot: empty\n");
2486}
2487
2488/**
2489 * xmlSchemaTypeDump:
2490 * @output: the file output
2491 * @type: a type structure
2492 *
2493 * Dump a SchemaType structure
2494 */
2495static void
2496xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2497{
2498 if (type == NULL) {
2499 fprintf(output, "Type: NULL\n");
2500 return;
2501 }
2502 fprintf(output, "Type: ");
2503 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002504 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002505 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002506 fprintf(output, "no name ");
2507 if (type->targetNamespace != NULL)
2508 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002509 switch (type->type) {
2510 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002511 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002512 break;
2513 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002514 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002515 break;
2516 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002517 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002518 break;
2519 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002520 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002521 break;
2522 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002523 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002524 break;
2525 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002526 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002527 break;
2528 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002529 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002530 break;
2531 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002532 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002533 break;
2534 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002535 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002536 break;
2537 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002538 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002539 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002540 }
2541 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002542 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002543 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002544 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002545 break;
2546 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002547 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002548 break;
2549 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002550 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002551 break;
2552 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002553 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002554 break;
2555 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002556 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002557 break;
2558 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002559 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002560 break;
2561 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002562 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002563 break;
2564 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002565 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002566 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002567 }
2568 fprintf(output, "\n");
2569 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002570 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002571 if (type->maxOccurs >= UNBOUNDED)
2572 fprintf(output, "max: unbounded\n");
2573 else if (type->maxOccurs != 1)
2574 fprintf(output, "max: %d\n", type->maxOccurs);
2575 else
2576 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002577 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002578 if (type->base != NULL) {
2579 fprintf(output, " base type: %s", type->base);
2580 if (type->baseNs != NULL)
2581 fprintf(output, " ns %s\n", type->baseNs);
2582 else
2583 fprintf(output, "\n");
2584 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002585 if (type->annot != NULL)
2586 xmlSchemaAnnotDump(output, type->annot);
2587 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002588 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002589
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002590 fprintf(output, " subtypes: ");
2591 while (sub != NULL) {
2592 fprintf(output, "%s ", sub->name);
2593 sub = sub->next;
2594 }
2595 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002596 }
2597
2598}
2599
2600/**
2601 * xmlSchemaDump:
2602 * @output: the file output
2603 * @schema: a schema structure
2604 *
2605 * Dump a Schema structure.
2606 */
2607void
2608xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2609{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002610 if (output == NULL)
2611 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002612 if (schema == NULL) {
2613 fprintf(output, "Schemas: NULL\n");
2614 return;
2615 }
2616 fprintf(output, "Schemas: ");
2617 if (schema->name != NULL)
2618 fprintf(output, "%s, ", schema->name);
2619 else
2620 fprintf(output, "no name, ");
2621 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002622 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002623 else
2624 fprintf(output, "no target namespace");
2625 fprintf(output, "\n");
2626 if (schema->annot != NULL)
2627 xmlSchemaAnnotDump(output, schema->annot);
2628
2629 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2630 output);
2631 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002632 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002633}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002634#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002635
2636/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002637 * *
2638 * Utilities *
2639 * *
2640 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002641
Daniel Veillardc0826a72004-08-10 14:17:33 +00002642/**
2643 * xmlSchemaGetPropNode:
2644 * @node: the element node
2645 * @name: the name of the attribute
2646 *
2647 * Seeks an attribute with a name of @name in
2648 * no namespace.
2649 *
2650 * Returns the attribute or NULL if not present.
2651 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002652static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002653xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002654{
2655 xmlAttrPtr prop;
2656
Daniel Veillardc0826a72004-08-10 14:17:33 +00002657 if ((node == NULL) || (name == NULL))
2658 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002659 prop = node->properties;
2660 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002661 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2662 return(prop);
2663 prop = prop->next;
2664 }
2665 return (NULL);
2666}
2667
2668/**
2669 * xmlSchemaGetPropNodeNs:
2670 * @node: the element node
2671 * @uri: the uri
2672 * @name: the name of the attribute
2673 *
2674 * Seeks an attribute with a local name of @name and
2675 * a namespace URI of @uri.
2676 *
2677 * Returns the attribute or NULL if not present.
2678 */
2679static xmlAttrPtr
2680xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2681{
2682 xmlAttrPtr prop;
2683
2684 if ((node == NULL) || (name == NULL))
2685 return(NULL);
2686 prop = node->properties;
2687 while (prop != NULL) {
2688 if ((prop->ns != NULL) &&
2689 xmlStrEqual(prop->name, BAD_CAST name) &&
2690 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002691 return(prop);
2692 prop = prop->next;
2693 }
2694 return (NULL);
2695}
2696
2697static const xmlChar *
2698xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2699{
2700 xmlChar *val;
2701 const xmlChar *ret;
2702
2703 val = xmlNodeGetContent(node);
2704 if (val == NULL)
2705 return(NULL);
2706 ret = xmlDictLookup(ctxt->dict, val, -1);
2707 xmlFree(val);
2708 return(ret);
2709}
2710
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002711/**
2712 * xmlSchemaGetProp:
2713 * @ctxt: the parser context
2714 * @node: the node
2715 * @name: the property name
2716 *
2717 * Read a attribute value and internalize the string
2718 *
2719 * Returns the string or NULL if not present.
2720 */
2721static const xmlChar *
2722xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2723 const char *name)
2724{
2725 xmlChar *val;
2726 const xmlChar *ret;
2727
2728 val = xmlGetProp(node, BAD_CAST name);
2729 if (val == NULL)
2730 return(NULL);
2731 ret = xmlDictLookup(ctxt->dict, val, -1);
2732 xmlFree(val);
2733 return(ret);
2734}
2735
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002736/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002737 * *
2738 * Parsing functions *
2739 * *
2740 ************************************************************************/
2741
2742/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002743 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002744 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002745 * @name: the element name
2746 * @ns: the element namespace
2747 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002748 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002749 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002750 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002751 */
2752static xmlSchemaElementPtr
2753xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002754 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002755{
2756 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002757
2758 if ((name == NULL) || (schema == NULL))
2759 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002760
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002761 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002762 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002763 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002764 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002765 } else
2766 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002767 /*
2768 * This one was removed, since top level element declarations have
2769 * the target namespace specified in targetNamespace of the <schema>
2770 * information element, even if elementFormDefault is "unqualified".
2771 */
2772
2773 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002774 if (xmlStrEqual(namespace, schema->targetNamespace))
2775 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2776 else
2777 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002778 if ((ret != NULL) &&
2779 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002780 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002781 }
William M. Bracke7091952004-05-11 15:09:58 +00002782 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002783
William M. Brack2f2a6632004-08-20 23:09:47 +00002784 /*
2785 * Removed since imported components will be hold by the main schema only.
2786 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002787 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002788 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002789 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002790 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002791 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002792 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002793 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2794 return (ret);
2795 } else
2796 ret = NULL;
2797 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002798 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002799#ifdef DEBUG
2800 if (ret == NULL) {
2801 if (namespace == NULL)
2802 fprintf(stderr, "Unable to lookup type %s", name);
2803 else
2804 fprintf(stderr, "Unable to lookup type %s:%s", name,
2805 namespace);
2806 }
2807#endif
2808 return (ret);
2809}
2810
2811/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002812 * xmlSchemaGetType:
2813 * @schema: the schemas context
2814 * @name: the type name
2815 * @ns: the type namespace
2816 *
2817 * Lookup a type in the schemas or the predefined types
2818 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002819 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002820 */
2821static xmlSchemaTypePtr
2822xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002823 const xmlChar * namespace)
2824{
Daniel Veillard4255d502002-04-16 15:50:10 +00002825 xmlSchemaTypePtr ret;
2826
2827 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002828 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002829 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002830 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002831 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002832 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 }
2834 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002835 if (ret != NULL)
2836 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002837 /*
2838 * Removed, since the imported components will be grafted on the
2839 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002840 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002841 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002842 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002843 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002844 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002845 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002846 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2847 return (ret);
2848 } else
2849 ret = NULL;
2850 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002851 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002852#ifdef DEBUG
2853 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002854 if (namespace == NULL)
2855 fprintf(stderr, "Unable to lookup type %s", name);
2856 else
2857 fprintf(stderr, "Unable to lookup type %s:%s", name,
2858 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002859 }
2860#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002861 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002862}
2863
Daniel Veillard3646d642004-06-02 19:19:14 +00002864/**
2865 * xmlSchemaGetAttribute:
2866 * @schema: the context of the schema
2867 * @name: the name of the attribute
2868 * @ns: the target namespace of the attribute
2869 *
2870 * Lookup a an attribute in the schema or imported schemas
2871 *
2872 * Returns the attribute declaration or NULL if not found.
2873 */
2874static xmlSchemaAttributePtr
2875xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2876 const xmlChar * namespace)
2877{
2878 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002879
2880 if ((name == NULL) || (schema == NULL))
2881 return (NULL);
2882
2883
2884 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2885 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2886 return (ret);
2887 else
2888 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002889 /*
2890 * Removed, since imported components will be hold by the main schema only.
2891 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002892 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002893 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002894 else
2895 import = xmlHashLookup(schema->schemasImports, namespace);
2896 if (import != NULL) {
2897 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2898 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2899 return (ret);
2900 } else
2901 ret = NULL;
2902 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002903 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002904#ifdef DEBUG
2905 if (ret == NULL) {
2906 if (namespace == NULL)
2907 fprintf(stderr, "Unable to lookup attribute %s", name);
2908 else
2909 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2910 namespace);
2911 }
2912#endif
2913 return (ret);
2914}
2915
2916/**
2917 * xmlSchemaGetAttributeGroup:
2918 * @schema: the context of the schema
2919 * @name: the name of the attribute group
2920 * @ns: the target namespace of the attribute group
2921 *
2922 * Lookup a an attribute group in the schema or imported schemas
2923 *
2924 * Returns the attribute group definition or NULL if not found.
2925 */
2926static xmlSchemaAttributeGroupPtr
2927xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2928 const xmlChar * namespace)
2929{
2930 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002931
2932 if ((name == NULL) || (schema == NULL))
2933 return (NULL);
2934
2935
2936 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2937 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2938 return (ret);
2939 else
2940 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002941 /*
2942 * Removed since imported components will be hold by the main schema only.
2943 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002944 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002945 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002946 else
2947 import = xmlHashLookup(schema->schemasImports, namespace);
2948 if (import != NULL) {
2949 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2950 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2951 return (ret);
2952 else
2953 ret = NULL;
2954 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002955 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002956#ifdef DEBUG
2957 if (ret == NULL) {
2958 if (namespace == NULL)
2959 fprintf(stderr, "Unable to lookup attribute group %s", name);
2960 else
2961 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2962 namespace);
2963 }
2964#endif
2965 return (ret);
2966}
2967
2968/**
2969 * xmlSchemaGetGroup:
2970 * @schema: the context of the schema
2971 * @name: the name of the group
2972 * @ns: the target namespace of the group
2973 *
2974 * Lookup a group in the schema or imported schemas
2975 *
2976 * Returns the group definition or NULL if not found.
2977 */
2978static xmlSchemaTypePtr
2979xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2980 const xmlChar * namespace)
2981{
2982 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002983
2984 if ((name == NULL) || (schema == NULL))
2985 return (NULL);
2986
2987
2988 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2989 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2990 return (ret);
2991 else
2992 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002993 /*
2994 * Removed since imported components will be hold by the main schema only.
2995 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002996 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002997 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002998 else
2999 import = xmlHashLookup(schema->schemasImports, namespace);
3000 if (import != NULL) {
3001 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3002 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3003 return (ret);
3004 else
3005 ret = NULL;
3006 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003007 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003008#ifdef DEBUG
3009 if (ret == NULL) {
3010 if (namespace == NULL)
3011 fprintf(stderr, "Unable to lookup group %s", name);
3012 else
3013 fprintf(stderr, "Unable to lookup group %s:%s", name,
3014 namespace);
3015 }
3016#endif
3017 return (ret);
3018}
3019
Daniel Veillard4255d502002-04-16 15:50:10 +00003020/************************************************************************
3021 * *
3022 * Parsing functions *
3023 * *
3024 ************************************************************************/
3025
3026#define IS_BLANK_NODE(n) \
3027 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3028
3029/**
3030 * xmlSchemaIsBlank:
3031 * @str: a string
3032 *
3033 * Check if a string is ignorable
3034 *
3035 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3036 */
3037static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003038xmlSchemaIsBlank(xmlChar * str)
3039{
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003041 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003043 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003044 return (0);
3045 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003046 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003047 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003048}
3049
3050/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003051 * xmlSchemaAddAssembledItem:
3052 * @ctxt: a schema parser context
3053 * @schema: the schema being built
3054 * @item: the item
3055 *
3056 * Add a item to the schema's list of current items.
3057 * This is used if the schema was already constructed and
3058 * new schemata need to be added to it.
3059 * *WARNING* this interface is highly subject to change.
3060 *
3061 * Returns 0 if suceeds and -1 if an internal error occurs.
3062 */
3063static int
3064xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3065 xmlSchemaTypePtr item)
3066{
3067 static int growSize = 100;
3068 xmlSchemaAssemblePtr ass;
3069
3070 ass = ctxt->assemble;
3071 if (ass->sizeItems < 0) {
3072 /* If disabled. */
3073 return (0);
3074 }
3075 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003076 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003077 if (ass->items == NULL) {
3078 xmlSchemaPErrMemory(ctxt,
3079 "allocating new item buffer", NULL);
3080 return (-1);
3081 }
3082 ass->sizeItems = growSize;
3083 } else if (ass->sizeItems <= ass->nbItems) {
3084 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003085 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003086 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3087 if (ass->items == NULL) {
3088 xmlSchemaPErrMemory(ctxt,
3089 "growing item buffer", NULL);
3090 ass->sizeItems = 0;
3091 return (-1);
3092 }
3093 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003094 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003095 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3096 return (0);
3097}
3098
3099/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003100 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003101 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003102 * @schema: the schema being built
3103 * @name: the item name
3104 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003105 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003106 * *WARNING* this interface is highly subject to change
3107 *
3108 * Returns the new struture or NULL in case of error
3109 */
3110static xmlSchemaNotationPtr
3111xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003112 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003113{
3114 xmlSchemaNotationPtr ret = NULL;
3115 int val;
3116
3117 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3118 return (NULL);
3119
3120 if (schema->notaDecl == NULL)
3121 schema->notaDecl = xmlHashCreate(10);
3122 if (schema->notaDecl == NULL)
3123 return (NULL);
3124
3125 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3126 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003127 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003128 return (NULL);
3129 }
3130 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003131 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003132 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3133 ret);
3134 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003135 /*
3136 * TODO: This should never happen, since a unique name will be computed.
3137 * If it fails, then an other internal error must have occured.
3138 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003139 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3140 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003141 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003142 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003143 xmlFree(ret);
3144 return (NULL);
3145 }
3146 return (ret);
3147}
3148
3149
3150/**
3151 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003152 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003153 * @schema: the schema being built
3154 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003155 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003156 *
3157 * Add an XML schema Attrribute declaration
3158 * *WARNING* this interface is highly subject to change
3159 *
3160 * Returns the new struture or NULL in case of error
3161 */
3162static xmlSchemaAttributePtr
3163xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003164 const xmlChar * name, const xmlChar * namespace,
3165 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003166{
3167 xmlSchemaAttributePtr ret = NULL;
3168 int val;
3169
3170 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3171 return (NULL);
3172
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003173#ifdef DEBUG
3174 fprintf(stderr, "Adding attribute %s\n", name);
3175 if (namespace != NULL)
3176 fprintf(stderr, " target namespace %s\n", namespace);
3177#endif
3178
Daniel Veillard4255d502002-04-16 15:50:10 +00003179 if (schema->attrDecl == NULL)
3180 schema->attrDecl = xmlHashCreate(10);
3181 if (schema->attrDecl == NULL)
3182 return (NULL);
3183
3184 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3185 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003186 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003187 return (NULL);
3188 }
3189 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003190 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003191 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003192 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003193 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003195 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003196 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003197 NULL, NULL, node,
3198 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 xmlFree(ret);
3200 return (NULL);
3201 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003202 if (ctxt->assemble != NULL)
3203 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 return (ret);
3205}
3206
3207/**
3208 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003209 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 * @schema: the schema being built
3211 * @name: the item name
3212 *
3213 * Add an XML schema Attrribute Group declaration
3214 *
3215 * Returns the new struture or NULL in case of error
3216 */
3217static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003218xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003219 xmlSchemaPtr schema, const xmlChar * name,
3220 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003221{
3222 xmlSchemaAttributeGroupPtr ret = NULL;
3223 int val;
3224
3225 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3226 return (NULL);
3227
3228 if (schema->attrgrpDecl == NULL)
3229 schema->attrgrpDecl = xmlHashCreate(10);
3230 if (schema->attrgrpDecl == NULL)
3231 return (NULL);
3232
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003233 ret =
3234 (xmlSchemaAttributeGroupPtr)
3235 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003236 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003237 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 return (NULL);
3239 }
3240 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003241 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003242 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003243 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003244 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003245 xmlSchemaPCustomErr(ctxt,
3246 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3247 NULL, NULL, node,
3248 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003249 xmlFree(ret);
3250 return (NULL);
3251 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003252 if (ctxt->assemble != NULL)
3253 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003254 return (ret);
3255}
3256
3257/**
3258 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003259 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 * @schema: the schema being built
3261 * @name: the type name
3262 * @namespace: the type namespace
3263 *
3264 * Add an XML schema Element declaration
3265 * *WARNING* this interface is highly subject to change
3266 *
3267 * Returns the new struture or NULL in case of error
3268 */
3269static xmlSchemaElementPtr
3270xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003271 const xmlChar * name, const xmlChar * namespace,
3272 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003273{
3274 xmlSchemaElementPtr ret = NULL;
3275 int val;
3276
3277 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3278 return (NULL);
3279
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003280#ifdef DEBUG
3281 fprintf(stderr, "Adding element %s\n", name);
3282 if (namespace != NULL)
3283 fprintf(stderr, " target namespace %s\n", namespace);
3284#endif
3285
Daniel Veillard4255d502002-04-16 15:50:10 +00003286 if (schema->elemDecl == NULL)
3287 schema->elemDecl = xmlHashCreate(10);
3288 if (schema->elemDecl == NULL)
3289 return (NULL);
3290
3291 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3292 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003293 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003294 return (NULL);
3295 }
3296 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003297 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003298 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003299 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003300 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003301 if (topLevel) {
3302 xmlSchemaPCustomErr(ctxt,
3303 XML_SCHEMAP_REDEFINED_ELEMENT,
3304 NULL, NULL, node,
3305 "A global element declaration with the name '%s' does "
3306 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003307 xmlFree(ret);
3308 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003309 } else {
3310 char buf[30];
3311
3312 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3313 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3314 namespace, ret);
3315 if (val != 0) {
3316 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003317 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003318 NULL, NULL, node,
3319 "Internal error: xmlSchemaAddElement, "
3320 "a dublicate element declaration with the name '%s' "
3321 "could not be added to the hash.", name);
3322 xmlFree(ret);
3323 return (NULL);
3324 }
3325 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003326
Daniel Veillard4255d502002-04-16 15:50:10 +00003327 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003328 if (ctxt->assemble != NULL)
3329 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003330 return (ret);
3331}
3332
3333/**
3334 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003335 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003336 * @schema: the schema being built
3337 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003338 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003339 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003340 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003341 * *WARNING* this interface is highly subject to change
3342 *
3343 * Returns the new struture or NULL in case of error
3344 */
3345static xmlSchemaTypePtr
3346xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003347 const xmlChar * name, const xmlChar * namespace,
3348 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003349{
3350 xmlSchemaTypePtr ret = NULL;
3351 int val;
3352
3353 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3354 return (NULL);
3355
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003356#ifdef DEBUG
3357 fprintf(stderr, "Adding type %s\n", name);
3358 if (namespace != NULL)
3359 fprintf(stderr, " target namespace %s\n", namespace);
3360#endif
3361
Daniel Veillard4255d502002-04-16 15:50:10 +00003362 if (schema->typeDecl == NULL)
3363 schema->typeDecl = xmlHashCreate(10);
3364 if (schema->typeDecl == NULL)
3365 return (NULL);
3366
3367 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3368 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003369 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003370 return (NULL);
3371 }
3372 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003373 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003374 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003375 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003376 if (val != 0) {
3377 if (ctxt->includes == 0) {
3378 xmlSchemaPCustomErr(ctxt,
3379 XML_SCHEMAP_REDEFINED_TYPE,
3380 NULL, NULL, node,
3381 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003382 xmlFree(ret);
3383 return (NULL);
3384 } else {
3385 xmlSchemaTypePtr prev;
3386
3387 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3388 if (prev == NULL) {
3389 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003390 XML_ERR_INTERNAL_ERROR,
3391 "Internal error: xmlSchemaAddType, on type "
3392 "'%s'.\n",
3393 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003394 xmlFree(ret);
3395 return (NULL);
3396 }
3397 ret->redef = prev->redef;
3398 prev->redef = ret;
3399 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003400 }
3401 ret->minOccurs = 1;
3402 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003403 ret->attributeUses = NULL;
3404 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003405 if (ctxt->assemble != NULL)
3406 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003407 return (ret);
3408}
3409
3410/**
3411 * xmlSchemaAddGroup:
3412 * @ctxt: a schema validation context
3413 * @schema: the schema being built
3414 * @name: the group name
3415 *
3416 * Add an XML schema Group definition
3417 *
3418 * Returns the new struture or NULL in case of error
3419 */
3420static xmlSchemaTypePtr
3421xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003422 const xmlChar *name, const xmlChar *namespaceName,
3423 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003424{
3425 xmlSchemaTypePtr ret = NULL;
3426 int val;
3427
3428 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3429 return (NULL);
3430
3431 if (schema->groupDecl == NULL)
3432 schema->groupDecl = xmlHashCreate(10);
3433 if (schema->groupDecl == NULL)
3434 return (NULL);
3435
3436 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3437 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003438 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003439 return (NULL);
3440 }
3441 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003442 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003443 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003444 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003445 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003446 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003447 xmlSchemaPCustomErr(ctxt,
3448 XML_SCHEMAP_REDEFINED_GROUP,
3449 NULL, NULL, node,
3450 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003451 xmlFree(ret);
3452 return (NULL);
3453 }
3454 ret->minOccurs = 1;
3455 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003456 if (ctxt->assemble != NULL)
3457 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003458 return (ret);
3459}
3460
Daniel Veillard3646d642004-06-02 19:19:14 +00003461/**
3462 * xmlSchemaNewWildcardNs:
3463 * @ctxt: a schema validation context
3464 *
3465 * Creates a new wildcard namespace constraint.
3466 *
3467 * Returns the new struture or NULL in case of error
3468 */
3469static xmlSchemaWildcardNsPtr
3470xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3471{
3472 xmlSchemaWildcardNsPtr ret;
3473
3474 ret = (xmlSchemaWildcardNsPtr)
3475 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3476 if (ret == NULL) {
3477 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3478 return (NULL);
3479 }
3480 ret->value = NULL;
3481 ret->next = NULL;
3482 return (ret);
3483}
3484
3485/**
3486 * xmlSchemaAddWildcard:
3487 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003488 * Adds a wildcard. It corresponds to a
3489 * xsd:anyAttribute and is used as storage for namespace
3490 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003491 *
3492 * Returns the new struture or NULL in case of error
3493 */
3494static xmlSchemaWildcardPtr
3495xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3496{
3497 xmlSchemaWildcardPtr ret = NULL;
3498
3499 if (ctxt == NULL)
3500 return (NULL);
3501
3502 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3503 if (ret == NULL) {
3504 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3505 return (NULL);
3506 }
3507 memset(ret, 0, sizeof(xmlSchemaWildcard));
3508 ret->minOccurs = 1;
3509 ret->maxOccurs = 1;
3510
3511 return (ret);
3512}
3513
Daniel Veillard4255d502002-04-16 15:50:10 +00003514/************************************************************************
3515 * *
3516 * Utilities for parsing *
3517 * *
3518 ************************************************************************/
3519
3520/**
3521 * xmlGetQNameProp:
3522 * @ctxt: a schema validation context
3523 * @node: a subtree containing XML Schema informations
3524 * @name: the attribute name
3525 * @namespace: the result namespace if any
3526 *
3527 * Extract a QName Attribute value
3528 *
3529 * Returns the NCName or NULL if not found, and also update @namespace
3530 * with the namespace URI
3531 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003532static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003533xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003534 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003535{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003536 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003537 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003538 const xmlChar *ret, *prefix;
3539 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003540 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003541
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003542 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003543 attr = xmlSchemaGetPropNode(node, name);
3544 if (attr == NULL)
3545 return (NULL);
3546 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003547
Daniel Veillard4255d502002-04-16 15:50:10 +00003548 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003549 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003550
Daniel Veillardba0153a2004-04-01 10:42:31 +00003551 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003552 ns = xmlSearchNs(node->doc, node, 0);
3553 if (ns) {
3554 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3555 return (val);
3556 }
3557 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003558 ret = xmlSplitQName3(val, &len);
3559 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003560 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003561 }
3562 ret = xmlDictLookup(ctxt->dict, ret, -1);
3563 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003564
3565 ns = xmlSearchNs(node->doc, node, prefix);
3566 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003567 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3568 NULL, NULL, (xmlNodePtr) attr,
3569 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003570 "The QName value '%s' has no corresponding namespace "
3571 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003572 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003573 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003574 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003575 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003576}
3577
3578/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003579 * xmlSchemaPValAttrNodeQNameValue:
3580 * @ctxt: a schema parser context
3581 * @schema: the schema context
3582 * @ownerDes: the designation of the parent element
3583 * @ownerItem: the parent as a schema object
3584 * @value: the QName value
3585 * @local: the resulting local part if found, the attribute value otherwise
3586 * @uri: the resulting namespace URI if found
3587 *
3588 * Extracts the local name and the URI of a QName value and validates it.
3589 * This one is intended to be used on attribute values that
3590 * should resolve to schema components.
3591 *
3592 * Returns 0, in case the QName is valid, a positive error code
3593 * if not valid and -1 if an internal error occurs.
3594 */
3595static int
3596xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3597 xmlSchemaPtr schema,
3598 xmlChar **ownerDes,
3599 xmlSchemaTypePtr ownerItem,
3600 xmlAttrPtr attr,
3601 const xmlChar *value,
3602 const xmlChar **uri,
3603 const xmlChar **prefix,
3604 const xmlChar **local)
3605{
3606 const xmlChar *pref;
3607 xmlNsPtr ns;
3608 int len, ret;
3609
3610 *uri = NULL;
3611 *local = NULL;
3612 if (prefix != 0)
3613 *prefix = NULL;
3614 ret = xmlValidateQName(value, 1);
3615 if (ret > 0) {
3616 xmlSchemaPSimpleTypeErr(ctxt,
3617 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3618 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003619 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3620 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003621 NULL, NULL, NULL);
3622 *local = value;
3623 return (ctxt->err);
3624 } else if (ret < 0)
3625 return (-1);
3626
3627 if (!strchr((char *) value, ':')) {
3628 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3629 if (ns)
3630 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3631 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3632 /*
3633 * This one takes care of included schemas with no
3634 * target namespace.
3635 */
3636 *uri = schema->targetNamespace;
3637 }
3638 *local = value;
3639 return (0);
3640 }
3641 /*
3642 * At this point xmlSplitQName3 has to return a local name.
3643 */
3644 *local = xmlSplitQName3(value, &len);
3645 *local = xmlDictLookup(ctxt->dict, *local, -1);
3646 pref = xmlDictLookup(ctxt->dict, value, len);
3647 if (prefix != 0)
3648 *prefix = pref;
3649 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3650 if (ns == NULL) {
3651 xmlSchemaPSimpleTypeErr(ctxt,
3652 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3653 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003654 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3655 "The QName value '%s' has no corresponding namespace "
3656 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003657 return (ctxt->err);
3658 } else {
3659 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3660 }
3661 return (0);
3662}
3663
3664/**
3665 * xmlSchemaPValAttrNodeQName:
3666 * @ctxt: a schema parser context
3667 * @schema: the schema context
3668 * @ownerDes: the designation of the owner element
3669 * @ownerItem: the owner as a schema object
3670 * @attr: the attribute node
3671 * @local: the resulting local part if found, the attribute value otherwise
3672 * @uri: the resulting namespace URI if found
3673 *
3674 * Extracts and validates the QName of an attribute value.
3675 * This one is intended to be used on attribute values that
3676 * should resolve to schema components.
3677 *
3678 * Returns 0, in case the QName is valid, a positive error code
3679 * if not valid and -1 if an internal error occurs.
3680 */
3681static int
3682xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3683 xmlSchemaPtr schema,
3684 xmlChar **ownerDes,
3685 xmlSchemaTypePtr ownerItem,
3686 xmlAttrPtr attr,
3687 const xmlChar **uri,
3688 const xmlChar **prefix,
3689 const xmlChar **local)
3690{
3691 const xmlChar *value;
3692
3693 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3694 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3695 ownerDes, ownerItem, attr, value, uri, prefix, local));
3696}
3697
3698/**
3699 * xmlSchemaPValAttrQName:
3700 * @ctxt: a schema parser context
3701 * @schema: the schema context
3702 * @ownerDes: the designation of the parent element
3703 * @ownerItem: the owner as a schema object
3704 * @ownerElem: the parent node of the attribute
3705 * @name: the name of the attribute
3706 * @local: the resulting local part if found, the attribute value otherwise
3707 * @uri: the resulting namespace URI if found
3708 *
3709 * Extracts and validates the QName of an attribute value.
3710 *
3711 * Returns 0, in case the QName is valid, a positive error code
3712 * if not valid and -1 if an internal error occurs.
3713 */
3714static int
3715xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3716 xmlSchemaPtr schema,
3717 xmlChar **ownerDes,
3718 xmlSchemaTypePtr ownerItem,
3719 xmlNodePtr ownerElem,
3720 const char *name,
3721 const xmlChar **uri,
3722 const xmlChar **prefix,
3723 const xmlChar **local)
3724{
3725 xmlAttrPtr attr;
3726
3727 attr = xmlSchemaGetPropNode(ownerElem, name);
3728 if (attr == NULL) {
3729 *local = NULL;
3730 *uri = NULL;
3731 return (0);
3732 }
3733 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3734 ownerDes, ownerItem, attr, uri, prefix, local));
3735}
3736
3737/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003738 * xmlGetMaxOccurs:
3739 * @ctxt: a schema validation context
3740 * @node: a subtree containing XML Schema informations
3741 *
3742 * Get the maxOccurs property
3743 *
3744 * Returns the default if not found, or the value
3745 */
3746static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003747xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3748 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003749{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003750 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003751 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003752 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003753
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003754 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3755 if (attr == NULL)
3756 return (def);
3757 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003758
3759 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003760 if (max != UNBOUNDED) {
3761 xmlSchemaPSimpleTypeErr(ctxt,
3762 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3763 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3764 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3765 val, NULL, NULL, NULL);
3766 return (def);
3767 } else
3768 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003769 }
3770
3771 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003772 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003773 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003774 if (*cur == 0) {
3775 xmlSchemaPSimpleTypeErr(ctxt,
3776 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3777 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3778 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3779 val, NULL, NULL, NULL);
3780 return (def);
3781 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003782 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003783 ret = ret * 10 + (*cur - '0');
3784 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003785 }
William M. Brack76e95df2003-10-18 16:20:14 +00003786 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003787 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003788 /*
3789 * TODO: Restrict the maximal value to Integer.
3790 */
3791 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3792 xmlSchemaPSimpleTypeErr(ctxt,
3793 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3794 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3795 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3796 val, NULL, NULL, NULL);
3797 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003798 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003799 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003800}
3801
3802/**
3803 * xmlGetMinOccurs:
3804 * @ctxt: a schema validation context
3805 * @node: a subtree containing XML Schema informations
3806 *
3807 * Get the minOccurs property
3808 *
3809 * Returns the default if not found, or the value
3810 */
3811static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003812xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3813 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003814{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003815 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003816 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003817 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003818
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003819 attr = xmlSchemaGetPropNode(node, "minOccurs");
3820 if (attr == NULL)
3821 return (def);
3822 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003823 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003824 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003825 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003826 if (*cur == 0) {
3827 xmlSchemaPSimpleTypeErr(ctxt,
3828 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3829 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3830 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3831 val, NULL, NULL, NULL);
3832 return (def);
3833 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003834 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003835 ret = ret * 10 + (*cur - '0');
3836 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003837 }
William M. Brack76e95df2003-10-18 16:20:14 +00003838 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003839 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003840 /*
3841 * TODO: Restrict the maximal value to Integer.
3842 */
3843 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3844 xmlSchemaPSimpleTypeErr(ctxt,
3845 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3846 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3847 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3848 val, NULL, NULL, NULL);
3849 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003850 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003851 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003852}
3853
3854/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003855 * xmlSchemaPGetBoolNodeValue:
3856 * @ctxt: a schema validation context
3857 * @ownerDes: owner designation
3858 * @ownerItem: the owner as a schema item
3859 * @node: the node holding the value
3860 *
3861 * Converts a boolean string value into 1 or 0.
3862 *
3863 * Returns 0 or 1.
3864 */
3865static int
3866xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3867 xmlChar **ownerDes,
3868 xmlSchemaTypePtr ownerItem,
3869 xmlNodePtr node)
3870{
3871 xmlChar *value = NULL;
3872 int res = 0;
3873
3874 value = xmlNodeGetContent(node);
3875 /*
3876 * 3.2.2.1 Lexical representation
3877 * An instance of a datatype that is defined as ·boolean·
3878 * can have the following legal literals {true, false, 1, 0}.
3879 */
3880 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3881 res = 1;
3882 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3883 res = 0;
3884 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3885 res = 1;
3886 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3887 res = 0;
3888 else {
3889 xmlSchemaPSimpleTypeErr(ctxt,
3890 XML_SCHEMAP_INVALID_BOOLEAN,
3891 ownerDes, ownerItem, node,
3892 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3893 "(1 | 0 | true | false)", BAD_CAST value,
3894 NULL, NULL, NULL);
3895 }
3896 if (value != NULL)
3897 xmlFree(value);
3898 return (res);
3899}
3900
3901/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003902 * xmlGetBooleanProp:
3903 * @ctxt: a schema validation context
3904 * @node: a subtree containing XML Schema informations
3905 * @name: the attribute name
3906 * @def: the default value
3907 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003908 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003909 *
3910 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003911 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003912 */
3913static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003914xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3915 xmlChar **ownerDes,
3916 xmlSchemaTypePtr ownerItem,
3917 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003918 const char *name, int def)
3919{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003920 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003921
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003922 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003923 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003924 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003925 /*
3926 * 3.2.2.1 Lexical representation
3927 * An instance of a datatype that is defined as ·boolean·
3928 * can have the following legal literals {true, false, 1, 0}.
3929 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003930 if (xmlStrEqual(val, BAD_CAST "true"))
3931 def = 1;
3932 else if (xmlStrEqual(val, BAD_CAST "false"))
3933 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003934 else if (xmlStrEqual(val, BAD_CAST "1"))
3935 def = 1;
3936 else if (xmlStrEqual(val, BAD_CAST "0"))
3937 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003938 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003939 xmlSchemaPSimpleTypeErr(ctxt,
3940 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 ownerDes, ownerItem, node,
3942 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3943 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003944 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003945 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003946}
3947
3948/************************************************************************
3949 * *
3950 * Shema extraction from an Infoset *
3951 * *
3952 ************************************************************************/
3953static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3954 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003955 xmlNodePtr node,
3956 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003957static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3958 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003959 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003960 xmlNodePtr node,
3961 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003962static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3963 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003964 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003965 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003966static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3967 xmlSchemaPtr schema,
3968 xmlNodePtr node);
3969static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3970 xmlSchemaPtr schema,
3971 xmlNodePtr node);
3972static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3973 ctxt,
3974 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003975 xmlNodePtr node,
3976 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003977static xmlSchemaAttributeGroupPtr
3978xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003979 xmlSchemaPtr schema, xmlNodePtr node,
3980 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003981static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3982 xmlSchemaPtr schema,
3983 xmlNodePtr node);
3984static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3985 xmlSchemaPtr schema,
3986 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003987static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003988xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3989 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003990
3991/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003992 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003993 *
3994 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003995 * @ownerDes: the designation of the parent element
3996 * @ownerItem: the schema object owner if existent
3997 * @attr: the schema attribute node being validated
3998 * @value: the value
3999 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004000 *
4001 * Validates a value against the given built-in type.
4002 * This one is intended to be used internally for validation
4003 * of schema attribute values during parsing of the schema.
4004 *
4005 * Returns 0 if the value is valid, a positive error code
4006 * number otherwise and -1 in case of an internal or API error.
4007 */
4008static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004009xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4010 xmlChar **ownerDes,
4011 xmlSchemaTypePtr ownerItem,
4012 xmlAttrPtr attr,
4013 const xmlChar *value,
4014 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004015{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004016
Daniel Veillardc0826a72004-08-10 14:17:33 +00004017 int ret = 0;
4018
4019 /*
4020 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4021 * one is really meant to be used internally, so better not.
4022 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004023 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004024 return (-1);
4025 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4026 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004027 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004028 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004029 "type '%s' is not a built-in type.\n",
4030 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004031 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004032 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004033 switch (type->builtInType) {
4034 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004035 case XML_SCHEMAS_QNAME:
4036 case XML_SCHEMAS_ANYURI:
4037 case XML_SCHEMAS_TOKEN:
4038 case XML_SCHEMAS_LANGUAGE:
4039 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4040 break;
4041
4042 /*
4043 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004044 ret = xmlValidateNCName(value, 1);
4045 break;
4046 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004047 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004048 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004049 "Internal error: xmlSchemaPvalueAttrNode, use "
4050 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4051 "for extracting QName valueues instead.\n",
4052 NULL, NULL);
4053 return (-1);
4054 case XML_SCHEMAS_ANYURI:
4055 if (value != NULL) {
4056 xmlURIPtr uri = xmlParseURI((const char *) value);
4057 if (uri == NULL)
4058 ret = 1;
4059 else
4060 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004061 }
4062 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004063 case XML_SCHEMAS_TOKEN: {
4064 const xmlChar *cur = value;
4065
4066 if (IS_BLANK_CH(*cur)) {
4067 ret = 1;
4068 } else while (*cur != 0) {
4069 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4070 ret = 1;
4071 break;
4072 } else if (*cur == ' ') {
4073 cur++;
4074 if ((*cur == 0) || (*cur == ' ')) {
4075 ret = 1;
4076 break;
4077 }
4078 } else {
4079 cur++;
4080 }
4081 }
4082 }
4083 break;
4084 case XML_SCHEMAS_LANGUAGE:
4085 if (xmlCheckLanguageID(value) != 1)
4086 ret = 1;
4087 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004088 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004089 default: {
4090 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004091 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004092 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004093 "valueidation using the type '%s' is not implemented "
4094 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004095 type->name, NULL);
4096 return (-1);
4097 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004098 }
4099 /*
4100 * TODO: Should we use the S4S error codes instead?
4101 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004102 if (ret < 0) {
4103 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4104 XML_SCHEMAP_INTERNAL,
4105 "Internal error: xmlSchemaPValAttrNodeValue, "
4106 "failed to validate a schema attribute value.\n",
4107 NULL, NULL);
4108 return (-1);
4109 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004110 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4111 xmlSchemaPSimpleTypeErr(ctxt,
4112 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4113 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004114 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004115 NULL, NULL, NULL);
4116 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4117 } else {
4118 xmlSchemaPSimpleTypeErr(ctxt,
4119 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4120 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004121 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004122 NULL, NULL, NULL);
4123 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4124 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004125 }
4126 return (ret);
4127}
4128
4129/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004130 * xmlSchemaPValAttrNode:
4131 *
4132 * @ctxt: a schema parser context
4133 * @ownerDes: the designation of the parent element
4134 * @ownerItem: the schema object owner if existent
4135 * @attr: the schema attribute node being validated
4136 * @type: the built-in type to be validated against
4137 * @value: the resulting value if any
4138 *
4139 * Extracts and validates a value against the given built-in type.
4140 * This one is intended to be used internally for validation
4141 * of schema attribute values during parsing of the schema.
4142 *
4143 * Returns 0 if the value is valid, a positive error code
4144 * number otherwise and -1 in case of an internal or API error.
4145 */
4146static int
4147xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4148 xmlChar **ownerDes,
4149 xmlSchemaTypePtr ownerItem,
4150 xmlAttrPtr attr,
4151 xmlSchemaTypePtr type,
4152 const xmlChar **value)
4153{
4154 const xmlChar *val;
4155
4156 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4157 return (-1);
4158
4159 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4160 if (value != NULL)
4161 *value = val;
4162
4163 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4164 val, type));
4165}
4166
4167/**
4168 * xmlSchemaPValAttr:
4169 *
4170 * @ctxt: a schema parser context
4171 * @node: the element node of the attribute
4172 * @ownerDes: the designation of the parent element
4173 * @ownerItem: the schema object owner if existent
4174 * @ownerElem: the owner element node
4175 * @name: the name of the schema attribute node
4176 * @type: the built-in type to be validated against
4177 * @value: the resulting value if any
4178 *
4179 * Extracts and validates a value against the given built-in type.
4180 * This one is intended to be used internally for validation
4181 * of schema attribute values during parsing of the schema.
4182 *
4183 * Returns 0 if the value is valid, a positive error code
4184 * number otherwise and -1 in case of an internal or API error.
4185 */
4186static int
4187xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4188 xmlChar **ownerDes,
4189 xmlSchemaTypePtr ownerItem,
4190 xmlNodePtr ownerElem,
4191 const char *name,
4192 xmlSchemaTypePtr type,
4193 const xmlChar **value)
4194{
4195 xmlAttrPtr attr;
4196
4197 if ((ctxt == NULL) || (type == NULL)) {
4198 if (value != NULL)
4199 *value = NULL;
4200 return (-1);
4201 }
4202 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4203 if (value != NULL)
4204 *value = NULL;
4205 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004206 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004207 "Internal error: xmlSchemaPValAttr, the given "
4208 "type '%s' is not a built-in type.\n",
4209 type->name, NULL);
4210 return (-1);
4211 }
4212 attr = xmlSchemaGetPropNode(ownerElem, name);
4213 if (attr == NULL) {
4214 if (value != NULL)
4215 *value = NULL;
4216 return (0);
4217 }
4218 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4219 type, value));
4220}
4221/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004222 * xmlSchemaParseAttrDecls:
4223 * @ctxt: a schema validation context
4224 * @schema: the schema being built
4225 * @node: a subtree containing XML Schema informations
4226 * @type: the hosting type
4227 *
4228 * parse a XML schema attrDecls declaration corresponding to
4229 * <!ENTITY % attrDecls
4230 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4231 */
4232static xmlNodePtr
4233xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4234 xmlNodePtr child, xmlSchemaTypePtr type)
4235{
4236 xmlSchemaAttributePtr lastattr, attr;
4237
4238 lastattr = NULL;
4239 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004240 (IS_SCHEMA(child, "attributeGroup"))) {
4241 attr = NULL;
4242 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004243 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004244 } else if (IS_SCHEMA(child, "attributeGroup")) {
4245 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004246 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247 }
4248 if (attr != NULL) {
4249 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004250 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4251 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4252 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 type->attributes = attr;
4254 lastattr = attr;
4255 } else {
4256 lastattr->next = attr;
4257 lastattr = attr;
4258 }
4259 }
4260 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004261 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004262 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004263}
4264
4265/**
4266 * xmlSchemaParseAnnotation:
4267 * @ctxt: a schema validation context
4268 * @schema: the schema being built
4269 * @node: a subtree containing XML Schema informations
4270 *
4271 * parse a XML schema Attrribute declaration
4272 * *WARNING* this interface is highly subject to change
4273 *
William M. Bracke7091952004-05-11 15:09:58 +00004274 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 * 1 in case of success.
4276 */
4277static xmlSchemaAnnotPtr
4278xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4279 xmlNodePtr node)
4280{
4281 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004282 xmlNodePtr child = NULL;
4283 xmlAttrPtr attr;
4284 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004285
Daniel Veillardc0826a72004-08-10 14:17:33 +00004286 /*
4287 * INFO: S4S completed.
4288 */
4289 /*
4290 * id = ID
4291 * {any attributes with non-schema namespace . . .}>
4292 * Content: (appinfo | documentation)*
4293 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004294 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4295 return (NULL);
4296 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004297 attr = node->properties;
4298 while (attr != NULL) {
4299 if (((attr->ns == NULL) &&
4300 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4301 ((attr->ns != NULL) &&
4302 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4303
4304 xmlSchemaPIllegalAttrErr(ctxt,
4305 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4306 NULL, NULL, attr);
4307 }
4308 attr = attr->next;
4309 }
4310 /* TODO: Check id. */
4311
4312 /*
4313 * And now for the children...
4314 */
4315 child = node->children;
4316 while (child != NULL) {
4317 if (IS_SCHEMA(child, "appinfo")) {
4318 /* TODO: make available the content of "appinfo". */
4319 /*
4320 * source = anyURI
4321 * {any attributes with non-schema namespace . . .}>
4322 * Content: ({any})*
4323 */
4324 attr = child->properties;
4325 while (attr != NULL) {
4326 if (((attr->ns == NULL) &&
4327 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4328 ((attr->ns != NULL) &&
4329 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004330
Daniel Veillardc0826a72004-08-10 14:17:33 +00004331 xmlSchemaPIllegalAttrErr(ctxt,
4332 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4333 NULL, NULL, attr);
4334 }
4335 attr = attr->next;
4336 }
4337 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4338 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4339 child = child->next;
4340 } else if (IS_SCHEMA(child, "documentation")) {
4341 /* TODO: make available the content of "documentation". */
4342 /*
4343 * source = anyURI
4344 * {any attributes with non-schema namespace . . .}>
4345 * Content: ({any})*
4346 */
4347 attr = child->properties;
4348 while (attr != NULL) {
4349 if (attr->ns == NULL) {
4350 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4351 xmlSchemaPIllegalAttrErr(ctxt,
4352 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4353 NULL, NULL, attr);
4354 }
4355 } else {
4356 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4357 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4358 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4359
4360 xmlSchemaPIllegalAttrErr(ctxt,
4361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4362 NULL, NULL, attr);
4363 }
4364 }
4365 attr = attr->next;
4366 }
4367 /*
4368 * Attribute "xml:lang".
4369 */
4370 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4371 if (attr != NULL)
4372 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4373 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4374 child = child->next;
4375 } else {
4376 if (!barked)
4377 xmlSchemaPContentErr(ctxt,
4378 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4379 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4380 barked = 1;
4381 child = child->next;
4382 }
4383 }
4384
Daniel Veillard4255d502002-04-16 15:50:10 +00004385 return (ret);
4386}
4387
4388/**
4389 * xmlSchemaParseFacet:
4390 * @ctxt: a schema validation context
4391 * @schema: the schema being built
4392 * @node: a subtree containing XML Schema informations
4393 *
4394 * parse a XML schema Facet declaration
4395 * *WARNING* this interface is highly subject to change
4396 *
4397 * Returns the new type structure or NULL in case of error
4398 */
4399static xmlSchemaFacetPtr
4400xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004401 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004402{
4403 xmlSchemaFacetPtr facet;
4404 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004405 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004406
4407 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4408 return (NULL);
4409
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004410 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411 if (facet == NULL) {
4412 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4413 return (NULL);
4414 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004416 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004417 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004418 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4419 "Facet %s has no value\n", node->name, NULL);
4420 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004421 return (NULL);
4422 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004423 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004424 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004425 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004427 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004428 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004430 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004431 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004433 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004435 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004436 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004438 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004439 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004443 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004444 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4445 } else if (IS_SCHEMA(node, "minLength")) {
4446 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4447 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004448 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4449 "Unknown facet type %s\n", node->name, NULL);
4450 xmlSchemaFreeFacet(facet);
4451 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004453 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004454 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004455 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4456 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4457 const xmlChar *fixed;
4458
4459 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4460 if (fixed != NULL) {
4461 if (xmlStrEqual(fixed, BAD_CAST "true"))
4462 facet->fixed = 1;
4463 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004464 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 child = node->children;
4466
4467 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004468 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4469 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 }
4471 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004472 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4473 "Facet %s has unexpected child content\n",
4474 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004475 }
4476 return (facet);
4477}
4478
4479/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004480 * xmlSchemaParseWildcardNs:
4481 * @ctxt: a schema parser context
4482 * @wildc: the wildcard, already created
4483 * @node: a subtree containing XML Schema informations
4484 *
4485 * Parses the attribute "processContents" and "namespace"
4486 * of a xsd:anyAttribute and xsd:any.
4487 * *WARNING* this interface is highly subject to change
4488 *
4489 * Returns 0 if everything goes fine, a positive error code
4490 * if something is not valid and -1 if an internal error occurs.
4491 */
4492static int
4493xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4494 xmlSchemaPtr schema,
4495 xmlSchemaWildcardPtr wildc,
4496 xmlNodePtr node)
4497{
4498 const xmlChar *pc, *ns, *dictnsItem;
4499 int ret = 0;
4500 xmlChar *nsItem;
4501 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4502 xmlAttrPtr attr;
4503
4504 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4505 if ((pc == NULL)
4506 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4507 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4508 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4509 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4510 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4511 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4512 } else {
4513 xmlSchemaPSimpleTypeErr(ctxt,
4514 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4515 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004516 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004517 NULL, NULL, NULL);
4518 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4519 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4520 }
4521 /*
4522 * Build the namespace constraints.
4523 */
4524 attr = xmlSchemaGetPropNode(node, "namespace");
4525 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4526 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4527 wildc->any = 1;
4528 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4529 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4530 if (wildc->negNsSet == NULL) {
4531 return (-1);
4532 }
4533 wildc->negNsSet->value = schema->targetNamespace;
4534 } else {
4535 const xmlChar *end, *cur;
4536
4537 cur = ns;
4538 do {
4539 while (IS_BLANK_CH(*cur))
4540 cur++;
4541 end = cur;
4542 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4543 end++;
4544 if (end == cur)
4545 break;
4546 nsItem = xmlStrndup(cur, end - cur);
4547 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4548 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4549 xmlSchemaPSimpleTypeErr(ctxt,
4550 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4551 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004552 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004553 "((##any | ##other) | List of (anyURI | "
4554 "(##targetNamespace | ##local)))",
4555 nsItem, NULL, NULL, NULL);
4556 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4557 } else {
4558 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4559 dictnsItem = schema->targetNamespace;
4560 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4561 dictnsItem = NULL;
4562 } else {
4563 /*
4564 * Validate the item (anyURI).
4565 */
4566 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4567 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4568 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4569 }
4570 /*
4571 * Avoid dublicate namespaces.
4572 */
4573 tmp = wildc->nsSet;
4574 while (tmp != NULL) {
4575 if (dictnsItem == tmp->value)
4576 break;
4577 tmp = tmp->next;
4578 }
4579 if (tmp == NULL) {
4580 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4581 if (tmp == NULL) {
4582 xmlFree(nsItem);
4583 return (-1);
4584 }
4585 tmp->value = dictnsItem;
4586 tmp->next = NULL;
4587 if (wildc->nsSet == NULL)
4588 wildc->nsSet = tmp;
4589 else
4590 lastNs->next = tmp;
4591 lastNs = tmp;
4592 }
4593
4594 }
4595 xmlFree(nsItem);
4596 cur = end;
4597 } while (*cur != 0);
4598 }
4599 return (ret);
4600}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004601
4602static int
4603xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4604 xmlSchemaTypePtr item,
4605 xmlNodePtr node,
4606 int minOccurs,
4607 int maxOccurs) {
4608
4609 if (maxOccurs != UNBOUNDED) {
4610 /*
4611 * TODO: Maby we should better not create the particle,
4612 * if min/max is invalid, since it could confuse the build of the
4613 * content model.
4614 */
4615 /*
4616 * 3.9.6 Schema Component Constraint: Particle Correct
4617 *
4618 */
4619 if (maxOccurs < 1) {
4620 /*
4621 * 2.2 {max occurs} must be greater than or equal to 1.
4622 */
4623 xmlSchemaPCustomAttrErr(ctxt,
4624 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4625 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4626 "The value must be greater than or equal to 1");
4627 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4628 } else if (minOccurs > maxOccurs) {
4629 /*
4630 * 2.1 {min occurs} must not be greater than {max occurs}.
4631 */
4632 xmlSchemaPCustomAttrErr(ctxt,
4633 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4634 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4635 "The value must not be greater than the value of 'maxOccurs'");
4636 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4637 }
4638 }
4639 return (0);
4640}
4641
Daniel Veillardc0826a72004-08-10 14:17:33 +00004642/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004643 * xmlSchemaParseAny:
4644 * @ctxt: a schema validation context
4645 * @schema: the schema being built
4646 * @node: a subtree containing XML Schema informations
4647 *
4648 * parse a XML schema Any declaration
4649 * *WARNING* this interface is highly subject to change
4650 *
4651 * Returns the new type structure or NULL in case of error
4652 */
4653static xmlSchemaTypePtr
4654xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4655 xmlNodePtr node)
4656{
4657 xmlSchemaTypePtr type;
4658 xmlNodePtr child = NULL;
4659 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004660 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004661 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004662
4663 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4664 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004665 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4666 "(nonNegativeInteger | unbounded)");
4667 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4668 "nonNegativeInteger");
4669 if ((minOccurs == 0) && (maxOccurs == 0))
4670 return (NULL);
4671
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004672 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004673 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004674 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004675 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004676 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004677 type->type = XML_SCHEMA_TYPE_ANY;
4678
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004679 /*
4680 * TODO: Use a particle component here.
4681 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004682 wildc = xmlSchemaAddWildcard(ctxt);
4683 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004684 * Check min/max sanity.
4685 */
4686 type->maxOccurs = maxOccurs;
4687 type->minOccurs = minOccurs;
4688 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4689 node, type->minOccurs, type->maxOccurs);
4690 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004691 * This is not nice, since it is won't be used as a attribute wildcard,
4692 * but better than adding a field to the structure.
4693 */
4694 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004695 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004696 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004697 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004698 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4699 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004700 }
4701 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004702 xmlSchemaPErr2(ctxt, node, child,
4703 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4704 "Sequence %s has unexpected content\n", type->name,
4705 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004706 }
4707
4708 return (type);
4709}
4710
4711/**
4712 * xmlSchemaParseNotation:
4713 * @ctxt: a schema validation context
4714 * @schema: the schema being built
4715 * @node: a subtree containing XML Schema informations
4716 *
4717 * parse a XML schema Notation declaration
4718 *
4719 * Returns the new structure or NULL in case of error
4720 */
4721static xmlSchemaNotationPtr
4722xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004723 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004724{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004725 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004726 xmlSchemaNotationPtr ret;
4727 xmlNodePtr child = NULL;
4728
4729 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4730 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004731 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004732 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004733 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4734 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004735 return (NULL);
4736 }
4737 ret = xmlSchemaAddNotation(ctxt, schema, name);
4738 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004739 return (NULL);
4740 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004741 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004742 child = node->children;
4743 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004744 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4745 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004746 }
4747 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004748 xmlSchemaPErr2(ctxt, node, child,
4749 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4750 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004751 }
4752
4753 return (ret);
4754}
4755
4756/**
4757 * xmlSchemaParseAnyAttribute:
4758 * @ctxt: a schema validation context
4759 * @schema: the schema being built
4760 * @node: a subtree containing XML Schema informations
4761 *
4762 * parse a XML schema AnyAttrribute declaration
4763 * *WARNING* this interface is highly subject to change
4764 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004765 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004766 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004767static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004768xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4769 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004770{
Daniel Veillard3646d642004-06-02 19:19:14 +00004771 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004772 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004773 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004774
4775 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4776 return (NULL);
4777
Daniel Veillard3646d642004-06-02 19:19:14 +00004778 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004779 if (ret == NULL) {
4780 return (NULL);
4781 }
William M. Bracke7091952004-05-11 15:09:58 +00004782 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004783 /*
4784 * Check for illegal attributes.
4785 */
4786 attr = node->properties;
4787 while (attr != NULL) {
4788 if (attr->ns == NULL) {
4789 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4790 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4791 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4792 xmlSchemaPIllegalAttrErr(ctxt,
4793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4794 NULL, NULL, attr);
4795 }
4796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4797 xmlSchemaPIllegalAttrErr(ctxt,
4798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4799 NULL, NULL, attr);
4800 }
4801 attr = attr->next;
4802 }
4803 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4804 /*
4805 * Parse the namespace list.
4806 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004807 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4808 xmlSchemaFreeWildcard(ret);
4809 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004810 }
4811 /*
4812 * And now for the children...
4813 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004814 child = node->children;
4815 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004816 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4817 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004818 }
4819 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004820 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004821 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4822 NULL, NULL, node, child,
4823 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004824 }
4825
4826 return (ret);
4827}
4828
4829
4830/**
4831 * xmlSchemaParseAttribute:
4832 * @ctxt: a schema validation context
4833 * @schema: the schema being built
4834 * @node: a subtree containing XML Schema informations
4835 *
4836 * parse a XML schema Attrribute declaration
4837 * *WARNING* this interface is highly subject to change
4838 *
William M. Bracke7091952004-05-11 15:09:58 +00004839 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004840 */
4841static xmlSchemaAttributePtr
4842xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004843 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004844{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004845 const xmlChar *name, *attrValue;
4846 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004847 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004848 xmlNodePtr child = NULL;
4849 xmlAttrPtr attr, nameAttr;
4850 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004851
4852 /*
4853 * Note that the w3c spec assumes the schema to be validated with schema
4854 * for schemas beforehand.
4855 *
4856 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004857 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004858
4859 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4860 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004861 attr = xmlSchemaGetPropNode(node, "ref");
4862 nameAttr = xmlSchemaGetPropNode(node, "name");
4863
4864 if ((attr == NULL) && (nameAttr == NULL)) {
4865 /*
4866 * 3.2.3 : 3.1
4867 * One of ref or name must be present, but not both
4868 */
4869 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4870 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4871 "One of the attributes 'ref' or 'name' must be present");
4872 return (NULL);
4873 }
4874 if ((topLevel) || (attr == NULL)) {
4875 if (nameAttr == NULL) {
4876 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4877 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4878 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004879 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004880 }
4881 } else
4882 isRef = 1;
4883
4884 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004885 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004886 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4887
4888 /*
4889 * Parse as attribute reference.
4890 */
4891 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4892 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4893 &refPrefix, &ref) != 0) {
4894 return (NULL);
4895 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004896 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004897 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004898 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004899 if (ret == NULL) {
4900 if (repName != NULL)
4901 xmlFree(repName);
4902 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004903 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004904 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4905 ret->node = node;
4906 ret->refNs = refNs;
4907 ret->refPrefix = refPrefix;
4908 ret->ref = ref;
4909 /*
4910 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4911 */
4912 if (nameAttr != NULL)
4913 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4914 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4915 "ref", "name");
4916 /*
4917 * Check for illegal attributes.
4918 */
4919 attr = node->properties;
4920 while (attr != NULL) {
4921 if (attr->ns == NULL) {
4922 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4923 xmlStrEqual(attr->name, BAD_CAST "form")) {
4924 /*
4925 * 3.2.3 : 3.2
4926 * If ref is present, then all of <simpleType>,
4927 * form and type must be absent.
4928 */
4929 xmlSchemaPIllegalAttrErr(ctxt,
4930 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4931 (xmlSchemaTypePtr) ret, attr);
4932 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4933 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4934 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4935 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4936 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4937 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4938 xmlSchemaPIllegalAttrErr(ctxt,
4939 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4940 &repName, (xmlSchemaTypePtr) ret, attr);
4941 }
4942 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4943 xmlSchemaPIllegalAttrErr(ctxt,
4944 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4945 &repName, (xmlSchemaTypePtr) ret, attr);
4946 }
4947 attr = attr->next;
4948 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004949 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004950 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004951
4952 /*
4953 * Parse as attribute declaration.
4954 */
4955 if (xmlSchemaPValAttrNode(ctxt,
4956 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4957 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4958 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004959 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004960 /*
4961 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4962 */
4963 /*
4964 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4965 */
4966 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4967 xmlSchemaPSimpleTypeErr(ctxt,
4968 XML_SCHEMAP_NO_XMLNS,
4969 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004970 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004971 "The value must not match 'xmlns'",
4972 NULL, NULL);
4973 if (repName != NULL)
4974 xmlFree(repName);
4975 return (NULL);
4976 }
4977 /*
4978 * Evaluate the target namespace
4979 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004980 if (topLevel) {
4981 ns = schema->targetNamespace;
4982 } else {
4983 attr = xmlSchemaGetPropNode(node, "form");
4984 if (attr != NULL) {
4985 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4986 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4987 ns = schema->targetNamespace;
4988 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4989 xmlSchemaPSimpleTypeErr(ctxt,
4990 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4991 &repName, NULL, (xmlNodePtr) attr,
4992 NULL, "(qualified | unqualified)",
4993 attrValue, NULL, NULL, NULL);
4994 }
4995 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4996 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004997 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004998 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 if (ret == NULL) {
5000 if (repName != NULL)
5001 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005002 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005003 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005004 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005005 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005006 if (topLevel)
5007 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5008 /*
5009 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5010 */
5011 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5012 xmlSchemaPCustomErr(ctxt,
5013 XML_SCHEMAP_NO_XSI,
5014 &repName, (xmlSchemaTypePtr) ret, node,
5015 "The target namespace must not match '%s'",
5016 xmlSchemaInstanceNs);
5017 }
5018 /*
5019 * Check for illegal attributes.
5020 */
5021 attr = node->properties;
5022 while (attr != NULL) {
5023 if (attr->ns == NULL) {
5024 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5025 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5026 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5027 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5028 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5029 if ((topLevel) ||
5030 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5031 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5032 xmlSchemaPIllegalAttrErr(ctxt,
5033 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5034 &repName, (xmlSchemaTypePtr) ret, attr);
5035 }
5036 }
5037 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5038 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5039 &repName, (xmlSchemaTypePtr) ret, attr);
5040 }
5041 attr = attr->next;
5042 }
5043 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5044 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005045 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005046 /* TODO: Check ID. */
5047 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005048 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005049 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005050 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005051 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5052 if (ret->defValue != NULL)
5053 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5054 /*
5055 * Attribute "default".
5056 */
5057 attr = xmlSchemaGetPropNode(node, "default");
5058 if (attr != NULL) {
5059 /*
5060 * 3.2.3 : 1
5061 * default and fixed must not both be present.
5062 */
5063 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5064 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5065 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5066 } else
5067 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5068 }
5069 if (topLevel == 0) {
5070 /*
5071 * Attribute "use".
5072 */
5073 attr = xmlSchemaGetPropNode(node, "use");
5074 if (attr != NULL) {
5075 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5076 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5077 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5078 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5079 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5080 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5081 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5082 else
5083 xmlSchemaPSimpleTypeErr(ctxt,
5084 XML_SCHEMAP_INVALID_ATTR_USE,
5085 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005086 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005087 attrValue, NULL, NULL, NULL);
5088 } else
5089 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5090 /*
5091 * 3.2.3 : 2
5092 * If default and use are both present, use must have
5093 * the actual value optional.
5094 */
5095 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5096 (ret->defValue != NULL) &&
5097 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5098 xmlSchemaPSimpleTypeErr(ctxt,
5099 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5100 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005101 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005102 "The value must be 'optional' if the attribute "
5103 "'default' is present as well", NULL, NULL);
5104 }
5105 }
5106 /*
5107 * And now for the children...
5108 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005109 child = node->children;
5110 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005111 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5112 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005113 }
5114 if (isRef) {
5115 if (child != NULL) {
5116 if (IS_SCHEMA(child, "simpleType"))
5117 /*
5118 * 3.2.3 : 3.2
5119 * If ref is present, then all of <simpleType>,
5120 * form and type must be absent.
5121 */
5122 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5123 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5124 "(annotation?)");
5125 else
5126 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5127 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5128 "(annotation?)");
5129 }
5130 } else {
5131 if (IS_SCHEMA(child, "simpleType")) {
5132 if (ret->typeName != NULL) {
5133 /*
5134 * 3.2.3 : 4
5135 * type and <simpleType> must not both be present.
5136 */
5137 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5138 &repName, (xmlSchemaTypePtr) ret, node, child,
5139 "The attribute 'type' and the <simpleType> child "
5140 "are mutually exclusive", NULL);
5141 } else
5142 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5143 child = child->next;
5144 }
5145 if (child != NULL)
5146 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5147 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5148 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005149 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005150 /*
5151 * Cleanup.
5152 */
5153 if (repName != NULL)
5154 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005155 return (ret);
5156}
5157
5158/**
5159 * xmlSchemaParseAttributeGroup:
5160 * @ctxt: a schema validation context
5161 * @schema: the schema being built
5162 * @node: a subtree containing XML Schema informations
5163 *
5164 * parse a XML schema Attribute Group declaration
5165 * *WARNING* this interface is highly subject to change
5166 *
5167 * Returns the attribute group or NULL in case of error.
5168 */
5169static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005170xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005171 xmlSchemaPtr schema, xmlNodePtr node,
5172 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005173{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005174 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005175 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005176 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005177 const xmlChar *oldcontainer;
5178 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005179
5180 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5181 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005182
5183 nameAttr = xmlSchemaGetPropNode(node, "name");
5184 attr = xmlSchemaGetPropNode(node, "ref");
5185 if ((topLevel) || (attr == NULL)) {
5186 /*
5187 * Parse as an attribute group definition.
5188 * Note that those are allowed at top level only.
5189 */
5190 if (nameAttr == NULL) {
5191 xmlSchemaPMissingAttrErr(ctxt,
5192 XML_SCHEMAP_S4S_ATTR_MISSING,
5193 NULL, NULL, node, "name", NULL);
5194 return (NULL);
5195 }
5196 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5197 /*
5198 * The name is crucial, exit if invalid.
5199 */
5200 if (xmlSchemaPValAttrNode(ctxt,
5201 NULL, NULL, nameAttr,
5202 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5203 return (NULL);
5204 }
5205 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5206 if (ret == NULL)
5207 return (NULL);
5208 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5209 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5210 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005211 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005212 } else {
5213 char buf[50];
5214 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5215
5216 /*
5217 * Parse as an attribute group definition reference.
5218 */
5219 if (attr == NULL) {
5220 xmlSchemaPMissingAttrErr(ctxt,
5221 XML_SCHEMAP_S4S_ATTR_MISSING,
5222 NULL, NULL, node, "ref", NULL);
5223 }
5224 xmlSchemaPValAttrNodeQName(ctxt, schema,
5225 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5226
5227 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5228 name = (const xmlChar *) buf;
5229 if (name == NULL) {
5230 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5231 "attribute group definition reference", node);
5232 return (NULL);
5233 }
5234 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5235 if (ret == NULL)
5236 return (NULL);
5237 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5238 ret->ref = ref;
5239 ret->refNs = refNs;
5240 /* TODO: Is @refPrefix currently used? */
5241 ret->refPrefix = refPrefix;
5242 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005243 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005244 /*
5245 * Check for illegal attributes.
5246 */
5247 attr = node->properties;
5248 while (attr != NULL) {
5249 if (attr->ns == NULL) {
5250 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5251 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5252 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5253 {
5254 xmlSchemaPIllegalAttrErr(ctxt,
5255 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5256 NULL, NULL, attr);
5257 }
5258 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5259 xmlSchemaPIllegalAttrErr(ctxt,
5260 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5261 NULL, NULL, attr);
5262 }
5263 attr = attr->next;
5264 }
5265 /* TODO: Validate "id" ? */
5266 /*
5267 * And now for the children...
5268 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005269 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005270 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005271 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005272 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005273 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5274 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005275 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005276 if (topLevel) {
5277 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5278 if (IS_SCHEMA(child, "anyAttribute")) {
5279 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5280 child = child->next;
5281 }
5282 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005283 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005284 xmlSchemaPContentErr(ctxt,
5285 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5286 NULL, NULL, node, child, NULL,
5287 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005288 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005289 ctxt->container = oldcontainer;
5290 return (ret);
5291}
5292
5293/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005294 * xmlSchemaPValAttrFormDefault:
5295 * @value: the value
5296 * @flags: the flags to be modified
5297 * @flagQualified: the specific flag for "qualified"
5298 *
5299 * Returns 0 if the value is valid, 1 otherwise.
5300 */
5301static int
5302xmlSchemaPValAttrFormDefault(const xmlChar *value,
5303 int *flags,
5304 int flagQualified)
5305{
5306 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5307 if ((*flags & flagQualified) == 0)
5308 *flags |= flagQualified;
5309 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5310 return (1);
5311
5312 return (0);
5313}
5314
5315/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005316 * xmlSchemaPValAttrBlockFinal:
5317 * @value: the value
5318 * @flags: the flags to be modified
5319 * @flagAll: the specific flag for "#all"
5320 * @flagExtension: the specific flag for "extension"
5321 * @flagRestriction: the specific flag for "restriction"
5322 * @flagSubstitution: the specific flag for "substitution"
5323 * @flagList: the specific flag for "list"
5324 * @flagUnion: the specific flag for "union"
5325 *
5326 * Validates the value of the attribute "final" and "block". The value
5327 * is converted into the specified flag values and returned in @flags.
5328 *
5329 * Returns 0 if the value is valid, 1 otherwise.
5330 */
5331
5332static int
5333xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5334 int *flags,
5335 int flagAll,
5336 int flagExtension,
5337 int flagRestriction,
5338 int flagSubstitution,
5339 int flagList,
5340 int flagUnion)
5341{
5342 int ret = 0;
5343
5344 /*
5345 * TODO: This does not check for dublicate entries.
5346 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005347 if (value == NULL)
5348 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005349 if (xmlStrEqual(value, BAD_CAST "#all")) {
5350 if (flagAll != -1)
5351 *flags |= flagAll;
5352 else {
5353 if (flagExtension != -1)
5354 *flags |= flagExtension;
5355 if (flagRestriction != -1)
5356 *flags |= flagRestriction;
5357 if (flagSubstitution != -1)
5358 *flags |= flagSubstitution;
5359 if (flagList != -1)
5360 *flags |= flagList;
5361 if (flagUnion != -1)
5362 *flags |= flagUnion;
5363 }
5364 } else {
5365 const xmlChar *end, *cur = value;
5366 xmlChar *item;
5367
5368 do {
5369 while (IS_BLANK_CH(*cur))
5370 cur++;
5371 end = cur;
5372 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5373 end++;
5374 if (end == cur)
5375 break;
5376 item = xmlStrndup(cur, end - cur);
5377 if (xmlStrEqual(item, BAD_CAST "extension")) {
5378 if (flagExtension != -1) {
5379 if ((*flags & flagExtension) == 0)
5380 *flags |= flagExtension;
5381 } else
5382 ret = 1;
5383 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5384 if (flagRestriction != -1) {
5385 if ((*flags & flagRestriction) == 0)
5386 *flags |= flagRestriction;
5387 } else
5388 ret = 1;
5389 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5390 if (flagSubstitution != -1) {
5391 if ((*flags & flagSubstitution) == 0)
5392 *flags |= flagSubstitution;
5393 } else
5394 ret = 1;
5395 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5396 if (flagList != -1) {
5397 if ((*flags & flagList) == 0)
5398 *flags |= flagList;
5399 } else
5400 ret = 1;
5401 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5402 if (flagUnion != -1) {
5403 if ((*flags & flagUnion) == 0)
5404 *flags |= flagUnion;
5405 } else
5406 ret = 1;
5407 } else
5408 ret = 1;
5409 if (item != NULL)
5410 xmlFree(item);
5411 cur = end;
5412 } while ((ret == 0) && (*cur != 0));
5413 }
5414
5415 return (ret);
5416}
5417
5418/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005419 * xmlSchemaParseElement:
5420 * @ctxt: a schema validation context
5421 * @schema: the schema being built
5422 * @node: a subtree containing XML Schema informations
5423 *
5424 * parse a XML schema Element declaration
5425 * *WARNING* this interface is highly subject to change
5426 *
William M. Bracke7091952004-05-11 15:09:58 +00005427 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005428 */
5429static xmlSchemaElementPtr
5430xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005431 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005432{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005433 const xmlChar *name = NULL;
5434 const xmlChar *attrValue;
5435 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005436 xmlSchemaElementPtr ret;
5437 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005438 const xmlChar *oldcontainer;
5439 xmlAttrPtr attr, nameAttr;
5440 int minOccurs, maxOccurs;
5441 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005442
5443 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5444 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005445
Daniel Veillard4255d502002-04-16 15:50:10 +00005446 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5447 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005448
Daniel Veillardc0826a72004-08-10 14:17:33 +00005449 oldcontainer = ctxt->container;
5450
5451 nameAttr = xmlSchemaGetPropNode(node, "name");
5452 attr = xmlSchemaGetPropNode(node, "ref");
5453 if ((topLevel) || (attr == NULL)) {
5454 if (nameAttr == NULL) {
5455 xmlSchemaPMissingAttrErr(ctxt,
5456 XML_SCHEMAP_S4S_ATTR_MISSING,
5457 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5458 "name", NULL);
5459 return (NULL);
5460 }
5461 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5462 } else {
5463 isRef = 1;
5464
5465 }
5466 /*
5467 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5468 * to no component at all
5469 * TODO: It might be better to validate the element, even if it won't be
5470 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005471 */
5472 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5473 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005474 if ((minOccurs == 0) && (maxOccurs == 0))
5475 return (NULL);
5476 /*
5477 * If we get a "ref" attribute on a local <element> we will assume it's
5478 * a reference - even if there's a "name" attribute; this seems to be more
5479 * robust.
5480 */
5481 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005482 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005483 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5484
5485 /*
5486 * Parse as a particle.
5487 */
5488 xmlSchemaPValAttrNodeQName(ctxt, schema,
5489 (xmlChar **) &xmlSchemaElemDesAttrRef,
5490 NULL, attr, &refNs, &refPrefix, &ref);
5491
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005492 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005493 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005494 if (ret == NULL) {
5495 if (repName != NULL)
5496 xmlFree(repName);
5497 return (NULL);
5498 }
5499 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5500 ret->node = node;
5501 ret->ref = ref;
5502 ret->refNs = refNs;
5503 ret->refPrefix = refPrefix;
5504 ret->flags |= XML_SCHEMAS_ELEM_REF;
5505 /*
5506 * Check for illegal attributes.
5507 */
5508 /*
5509 * 3.3.3 : 2.1
5510 * One of ref or name must be present, but not both
5511 */
5512 if (nameAttr != NULL) {
5513 xmlSchemaPMutualExclAttrErr(ctxt,
5514 XML_SCHEMAP_SRC_ELEMENT_2_1,
5515 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5516 "ref", "name");
5517 }
5518 /* 3.3.3 : 2.2 */
5519 attr = node->properties;
5520 while (attr != NULL) {
5521 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005522 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5523 xmlStrEqual(attr->name, BAD_CAST "name") ||
5524 xmlStrEqual(attr->name, BAD_CAST "id") ||
5525 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5526 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5527 {
5528 attr = attr->next;
5529 continue;
5530 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005531 xmlSchemaPCustomAttrErr(ctxt,
5532 XML_SCHEMAP_SRC_ELEMENT_2_2,
5533 &repName, (xmlSchemaTypePtr) ret, attr,
5534 "Only the attributes 'minOccurs', 'maxOccurs' and "
5535 "'id' are allowed in addition to 'ref'");
5536 break;
5537 }
5538 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5539 xmlSchemaPIllegalAttrErr(ctxt,
5540 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5541 &repName, (xmlSchemaTypePtr) ret, attr);
5542 }
5543 attr = attr->next;
5544 }
5545 } else {
5546 const xmlChar *ns = NULL, *fixed;
5547
5548 /*
5549 * Parse as an element declaration.
5550 */
5551 if (xmlSchemaPValAttrNode(ctxt,
5552 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5553 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5554 return (NULL);
5555 /*
5556 * Evaluate the target namespace.
5557 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005558 if (topLevel) {
5559 ns = schema->targetNamespace;
5560 } else {
5561 attr = xmlSchemaGetPropNode(node, "form");
5562 if (attr != NULL) {
5563 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5564 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005565 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005566 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5567 xmlSchemaPSimpleTypeErr(ctxt,
5568 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5569 &repName, NULL, (xmlNodePtr) attr,
5570 NULL, "(qualified | unqualified)",
5571 attrValue, NULL, NULL, NULL);
5572 }
5573 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5574 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005575 }
5576 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005577 if (ret == NULL) {
5578 if (repName != NULL)
5579 xmlFree(repName);
5580 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005581 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005582 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005583 ret->node = node;
5584 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005585 /*
5586 * Check for illegal attributes.
5587 */
William M. Bracke7091952004-05-11 15:09:58 +00005588 attr = node->properties;
5589 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 if (attr->ns == NULL) {
5591 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5592 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5593 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5594 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5595 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5596 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005597 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5598 {
5599 if (topLevel == 0) {
5600 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005601 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005602 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5603 {
5604 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5605 /*
5606 * 3.3.6 : 3 If there is a non-·absent· {substitution
5607 * group affiliation}, then {scope} must be global.
5608 * TODO: This one is redundant, since the S4S does
5609 * prohibit this attribute on local declarations already;
5610 * so why an explicit error code? Weird spec.
5611 * TODO: Move this to the proper constraint layer.
5612 * TODO: Or better wait for spec 1.1 to come.
5613 */
5614 xmlSchemaPIllegalAttrErr(ctxt,
5615 XML_SCHEMAP_E_PROPS_CORRECT_3,
5616 &repName, (xmlSchemaTypePtr) ret, attr);
5617 } else {
5618 xmlSchemaPIllegalAttrErr(ctxt,
5619 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5620 &repName, (xmlSchemaTypePtr) ret, attr);
5621 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005622 }
5623 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5624 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5625 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5626
5627 xmlSchemaPIllegalAttrErr(ctxt,
5628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5629 &repName, (xmlSchemaTypePtr) ret, attr);
5630 }
5631 }
5632 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5633
5634 xmlSchemaPIllegalAttrErr(ctxt,
5635 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5636 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005637 }
5638 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005639 }
William M. Bracke7091952004-05-11 15:09:58 +00005640 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005641 * Extract/validate attributes.
5642 */
5643 if (topLevel) {
5644 /*
5645 * Process top attributes of global element declarations here.
5646 */
5647 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5648 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5649 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5650 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5651 &(ret->substGroupNs), NULL, &(ret->substGroup));
5652 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5653 node, "abstract", 0))
5654 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5655 /*
5656 * Attribute "final".
5657 */
5658 attr = xmlSchemaGetPropNode(node, "final");
5659 if (attr == NULL) {
5660 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5661 } else {
5662 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5663 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5664 -1,
5665 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5666 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5667 xmlSchemaPSimpleTypeErr(ctxt,
5668 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5669 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005670 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005671 attrValue, NULL, NULL, NULL);
5672 }
5673 }
5674 }
5675 /*
5676 * Attribute "block".
5677 */
5678 attr = xmlSchemaGetPropNode(node, "block");
5679 if (attr == NULL) {
5680 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5681 } else {
5682 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5683 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5684 -1,
5685 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5686 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5687 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5688 xmlSchemaPSimpleTypeErr(ctxt,
5689 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5690 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005691 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005692 "restriction | substitution))", attrValue,
5693 NULL, NULL, NULL);
5694 }
5695 }
5696 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5697 node, "nillable", 0))
5698 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005699
Daniel Veillardc0826a72004-08-10 14:17:33 +00005700 xmlSchemaPValAttrQName(ctxt, schema,
5701 &repName, (xmlSchemaTypePtr) ret, node,
5702 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005703
Daniel Veillardc0826a72004-08-10 14:17:33 +00005704 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5705 attr = xmlSchemaGetPropNode(node, "fixed");
5706 if (attr != NULL) {
5707 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5708 if (ret->value != NULL) {
5709 /*
5710 * 3.3.3 : 1
5711 * default and fixed must not both be present.
5712 */
5713 xmlSchemaPMutualExclAttrErr(ctxt,
5714 XML_SCHEMAP_SRC_ELEMENT_1,
5715 &repName, (xmlSchemaTypePtr) ret, attr,
5716 "default", "fixed");
5717 } else {
5718 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5719 ret->value = fixed;
5720 }
5721 }
5722 }
5723 /*
5724 * Extract/validate common attributes.
5725 */
5726 /* TODO: Check ID: */
5727 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5728 ret->minOccurs = minOccurs;
5729 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005730 if (topLevel != 1)
5731 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5732 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005733 /*
5734 * And now for the children...
5735 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005736 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005737 child = node->children;
5738 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005739 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5740 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005741 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005742 if (isRef) {
5743 if (child != NULL) {
5744 xmlSchemaPContentErr(ctxt,
5745 XML_SCHEMAP_SRC_ELEMENT_2_2,
5746 &repName, (xmlSchemaTypePtr) ret, node, child,
5747 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005748 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005749 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005750 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005751 /*
5752 * 3.3.3 : 3
5753 * "type" and either <simpleType> or <complexType> are mutually
5754 * exclusive
5755 */
William M. Bracke7091952004-05-11 15:09:58 +00005756 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005757 xmlSchemaPContentErr(ctxt,
5758 XML_SCHEMAP_SRC_ELEMENT_3,
5759 &repName, (xmlSchemaTypePtr) ret, node, child,
5760 "The attribute 'type' and the <complexType> child are "
5761 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005762 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005763 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005764 child = child->next;
5765 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005766 /*
5767 * 3.3.3 : 3
5768 * "type" and either <simpleType> or <complexType> are
5769 * mutually exclusive
5770 */
William M. Bracke7091952004-05-11 15:09:58 +00005771 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005772 xmlSchemaPContentErr(ctxt,
5773 XML_SCHEMAP_SRC_ELEMENT_3,
5774 &repName, (xmlSchemaTypePtr) ret, node, child,
5775 "The attribute 'type' and the <simpleType> child are "
5776 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005777 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005778 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005779 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005780 }
William M. Bracke7091952004-05-11 15:09:58 +00005781 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005782 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcik48307f42004-11-12 15:16:25 +00005783 TODO child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00005784 }
5785 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005786 xmlSchemaPContentErr(ctxt,
5787 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5788 &repName, (xmlSchemaTypePtr) ret, node, child,
5789 NULL, "(annotation?, ((simpleType | complexType)?, "
5790 "(unique | key | keyref)*))");
5791 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005792
Daniel Veillardc0826a72004-08-10 14:17:33 +00005793 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005794 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005795 /*
5796 * Cleanup.
5797 */
5798 if (repName != NULL)
5799 xmlFree(repName);
5800 /*
5801 * NOTE: Element Declaration Representation OK 4. will be checked at a
5802 * different layer.
5803 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005804 return (ret);
5805}
5806
5807/**
5808 * xmlSchemaParseUnion:
5809 * @ctxt: a schema validation context
5810 * @schema: the schema being built
5811 * @node: a subtree containing XML Schema informations
5812 *
5813 * parse a XML schema Union definition
5814 * *WARNING* this interface is highly subject to change
5815 *
William M. Bracke7091952004-05-11 15:09:58 +00005816 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 * 1 in case of success.
5818 */
5819static xmlSchemaTypePtr
5820xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005821 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005822{
5823 xmlSchemaTypePtr type, subtype, last = NULL;
5824 xmlNodePtr child = NULL;
5825 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005826 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005827
5828 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5829 return (NULL);
5830
William M. Brack2f2a6632004-08-20 23:09:47 +00005831 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5832 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005833 if (type == NULL)
5834 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005835 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005836 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005837 /*
5838 * Check for illegal attributes.
5839 */
5840 attr = node->properties;
5841 while (attr != NULL) {
5842 if (attr->ns == NULL) {
5843 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5844 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5845 xmlSchemaPIllegalAttrErr(ctxt,
5846 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5847 NULL, type, attr);
5848 }
5849 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5850 xmlSchemaPIllegalAttrErr(ctxt,
5851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5852 NULL, type, attr);
5853 }
5854 attr = attr->next;
5855 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005856 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005857 /*
5858 * Attribute "memberTypes". This is a list of QNames.
5859 * TODO: Validate the QNames.
5860 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005861 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005862 /*
5863 * And now for the children...
5864 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005865 child = node->children;
5866 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005867 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5868 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005869 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005870 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005871 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005872 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005873 if (subtype != NULL) {
5874 if (last == NULL) {
5875 type->subtypes = subtype;
5876 last = subtype;
5877 } else {
5878 last->next = subtype;
5879 last = subtype;
5880 }
5881 last->next = NULL;
5882 }
5883 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005884 }
5885 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005886 /* TODO: Think about the error code. */
5887 xmlSchemaPContentErr(ctxt,
5888 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5889 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005890 }
5891 return (type);
5892}
5893
5894/**
5895 * xmlSchemaParseList:
5896 * @ctxt: a schema validation context
5897 * @schema: the schema being built
5898 * @node: a subtree containing XML Schema informations
5899 *
5900 * parse a XML schema List definition
5901 * *WARNING* this interface is highly subject to change
5902 *
William M. Bracke7091952004-05-11 15:09:58 +00005903 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005904 * 1 in case of success.
5905 */
5906static xmlSchemaTypePtr
5907xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005908 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005909{
5910 xmlSchemaTypePtr type, subtype;
5911 xmlNodePtr child = NULL;
5912 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005913 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005914
5915 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5916 return (NULL);
5917
William M. Brack2f2a6632004-08-20 23:09:47 +00005918 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5919 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005920 if (type == NULL)
5921 return (NULL);
5922 type->node = node;
5923 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005924 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005925 /*
5926 * Check for illegal attributes.
5927 */
5928 attr = node->properties;
5929 while (attr != NULL) {
5930 if (attr->ns == NULL) {
5931 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5932 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5933 xmlSchemaPIllegalAttrErr(ctxt,
5934 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5935 NULL, type, attr);
5936 }
5937 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5938 xmlSchemaPIllegalAttrErr(ctxt,
5939 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5940 NULL, type, attr);
5941 }
5942 attr = attr->next;
5943 }
5944 /*
5945 * Attribute "itemType".
5946 */
5947 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5948 node, "itemType", &(type->baseNs), NULL, &(type->base));
5949 /*
5950 * And now for the children...
5951 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005952 child = node->children;
5953 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005954 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5955 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005956 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005957 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005958 if (IS_SCHEMA(child, "simpleType")) {
5959 if (type->base != NULL) {
5960 xmlSchemaPCustomErr(ctxt,
5961 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5962 NULL, type, node,
5963 "The attribute 'itemType' and the <simpleType> child "
5964 "are mutually exclusive", NULL);
5965 } else {
5966 subtype = (xmlSchemaTypePtr)
5967 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5968 type->subtypes = subtype;
5969 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005970 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005971 }
5972 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005973 /* TODO: Think about the error code. */
5974 xmlSchemaPContentErr(ctxt,
5975 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5976 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005977 }
5978 return (type);
5979}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005980
Daniel Veillard4255d502002-04-16 15:50:10 +00005981/**
5982 * xmlSchemaParseSimpleType:
5983 * @ctxt: a schema validation context
5984 * @schema: the schema being built
5985 * @node: a subtree containing XML Schema informations
5986 *
5987 * parse a XML schema Simple Type definition
5988 * *WARNING* this interface is highly subject to change
5989 *
William M. Bracke7091952004-05-11 15:09:58 +00005990 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005991 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005992 */
5993static xmlSchemaTypePtr
5994xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005995 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005996{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005997 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005998 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005999 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006000 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006001 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006002
6003 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6004 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006005
Daniel Veillardc0826a72004-08-10 14:17:33 +00006006 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006007 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006008 if (attr == NULL) {
6009 xmlSchemaPMissingAttrErr(ctxt,
6010 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006011 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006012 "name", NULL);
6013 return (NULL);
6014 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006015 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006016 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006017 return (NULL);
6018 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006019 }
6020
6021 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006022 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006023
Daniel Veillard01fa6152004-06-29 17:04:39 +00006024 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006025 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006026 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006027 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006028 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006029 if (type == NULL)
6030 return (NULL);
6031 type->node = node;
6032 type->type = XML_SCHEMA_TYPE_SIMPLE;
6033 /*
6034 * Check for illegal attributes.
6035 */
6036 attr = node->properties;
6037 while (attr != NULL) {
6038 if (attr->ns == NULL) {
6039 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6040 xmlSchemaPIllegalAttrErr(ctxt,
6041 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006042 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006043 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006044 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6045 xmlSchemaPIllegalAttrErr(ctxt,
6046 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006047 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006048 }
6049 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006050 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006051 } else {
6052 /*
6053 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006054 *
6055 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006056 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006057 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006058 if (type == NULL)
6059 return (NULL);
6060 type->node = node;
6061 type->type = XML_SCHEMA_TYPE_SIMPLE;
6062 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6063 /*
6064 * Check for illegal attributes.
6065 */
6066 attr = node->properties;
6067 while (attr != NULL) {
6068 if (attr->ns == NULL) {
6069 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6070 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006071 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006072 xmlSchemaPIllegalAttrErr(ctxt,
6073 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006074 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006075 }
6076 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6077 xmlSchemaPIllegalAttrErr(ctxt,
6078 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006079 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006080 }
6081 attr = attr->next;
6082 }
6083 /*
6084 * Attribute "final".
6085 */
6086 attr = xmlSchemaGetPropNode(node, "final");
6087 if (attr == NULL) {
6088 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6089 } else {
6090 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6091 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6092 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6093 XML_SCHEMAS_TYPE_FINAL_LIST,
6094 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6095
6096 xmlSchemaPSimpleTypeErr(ctxt,
6097 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006098 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006099 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006100 attrValue, NULL, NULL, NULL);
6101 }
6102 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006103 }
6104 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006105 /* TODO: Check id. */
6106 type->id = xmlSchemaGetProp(ctxt, node, "id");
6107 /*
6108 * And now for the children...
6109 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006110 oldCtxtType = ctxt->ctxtType;
6111 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006112 ctxt->ctxtType = type;
6113 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006114 child = node->children;
6115 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006116 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6117 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006118 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006119 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006120 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006121 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006122 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006123 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006124 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006125 subtype = (xmlSchemaTypePtr)
6126 xmlSchemaParseList(ctxt, schema, child);
6127 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006128 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006129 subtype = (xmlSchemaTypePtr)
6130 xmlSchemaParseUnion(ctxt, schema, child);
6131 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006132 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006133 type->subtypes = subtype;
6134 if ((child != NULL) || (subtype == NULL)) {
6135 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006136 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006137 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006138 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006139 ctxt->parentItem = oldParentItem;
6140 ctxt->ctxtType = oldCtxtType;
6141 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006142
Daniel Veillard4255d502002-04-16 15:50:10 +00006143 return (type);
6144}
6145
6146
6147/**
6148 * xmlSchemaParseGroup:
6149 * @ctxt: a schema validation context
6150 * @schema: the schema being built
6151 * @node: a subtree containing XML Schema informations
6152 *
6153 * parse a XML schema Group definition
6154 * *WARNING* this interface is highly subject to change
6155 *
William M. Bracke7091952004-05-11 15:09:58 +00006156 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006157 * 1 in case of success.
6158 */
6159static xmlSchemaTypePtr
6160xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006161 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006162{
6163 xmlSchemaTypePtr type, subtype;
6164 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006165 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006166 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006167 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006168 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006169
6170 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6171 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006172 /*
6173 * TODO: Validate the element even if no item is created
6174 * (i.e. min/maxOccurs == 0).
6175 */
6176 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6177 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6178 if ((minOccurs == 0) && (maxOccurs == 0)) {
6179 return (NULL);
6180 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006181 if (topLevel)
6182 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006183 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006184 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006185 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6186 if (ref == NULL) {
6187 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006188 XML_SCHEMAP_GROUP_NONAME_NOREF,
6189 "Group definition or particle: One of the attributes \"name\" "
6190 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006191 return (NULL);
6192 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006193 if (refNs == NULL)
6194 refNs = schema->targetNamespace;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006195 snprintf(buf, 49, "#GrRef %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006196 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006197 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006198 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006199 if (type == NULL)
6200 return (NULL);
6201 type->node = node;
6202 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006203 if (topLevel)
6204 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006205 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006206 type->ref = ref;
6207 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006208 type->minOccurs = minOccurs;
6209 type->maxOccurs = maxOccurs;
6210 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006211 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006212
6213 child = node->children;
6214 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006215 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6216 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006217 }
6218 subtype = NULL;
6219 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006220 subtype = (xmlSchemaTypePtr)
6221 xmlSchemaParseAll(ctxt, schema, child);
6222 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006223 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006224 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6225 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006226 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006227 subtype = (xmlSchemaTypePtr)
6228 xmlSchemaParseSequence(ctxt, schema, child);
6229 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006230 }
6231 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006232 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006233 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006234 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006235 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006236 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006237 }
6238
6239 return (type);
6240}
6241
6242/**
6243 * xmlSchemaParseAll:
6244 * @ctxt: a schema validation context
6245 * @schema: the schema being built
6246 * @node: a subtree containing XML Schema informations
6247 *
6248 * parse a XML schema All definition
6249 * *WARNING* this interface is highly subject to change
6250 *
William M. Bracke7091952004-05-11 15:09:58 +00006251 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006252 * 1 in case of success.
6253 */
6254static xmlSchemaTypePtr
6255xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006256 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006257{
6258 xmlSchemaTypePtr type, subtype, last = NULL;
6259 xmlNodePtr child = NULL;
6260 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006261 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006262
6263 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6264 return (NULL);
6265
6266
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006267 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006268 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006269 if (type == NULL)
6270 return (NULL);
6271 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006272 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006273 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006274
6275 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6276 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006277
6278 oldcontainer = ctxt->container;
6279 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006280 child = node->children;
6281 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006282 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6283 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006284 }
6285 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006286 subtype = (xmlSchemaTypePtr)
6287 xmlSchemaParseElement(ctxt, schema, child, 0);
6288 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006289 if (subtype->minOccurs > 1)
6290 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006291 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006292 NULL, NULL);
6293 if (subtype->maxOccurs > 1)
6294 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006296 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006297 if (last == NULL) {
6298 type->subtypes = subtype;
6299 last = subtype;
6300 } else {
6301 last->next = subtype;
6302 last = subtype;
6303 }
6304 last->next = NULL;
6305 }
6306 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006307 }
6308 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006309 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006310 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006311 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006312 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006313 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006314 return (type);
6315}
6316
6317/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006318 * xmlSchemaCleanupDoc:
6319 * @ctxt: a schema validation context
6320 * @node: the root of the document.
6321 *
6322 * removes unwanted nodes in a schemas document tree
6323 */
6324static void
6325xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6326{
6327 xmlNodePtr delete, cur;
6328
6329 if ((ctxt == NULL) || (root == NULL)) return;
6330
6331 /*
6332 * Remove all the blank text nodes
6333 */
6334 delete = NULL;
6335 cur = root;
6336 while (cur != NULL) {
6337 if (delete != NULL) {
6338 xmlUnlinkNode(delete);
6339 xmlFreeNode(delete);
6340 delete = NULL;
6341 }
6342 if (cur->type == XML_TEXT_NODE) {
6343 if (IS_BLANK_NODE(cur)) {
6344 if (xmlNodeGetSpacePreserve(cur) != 1) {
6345 delete = cur;
6346 }
6347 }
6348 } else if ((cur->type != XML_ELEMENT_NODE) &&
6349 (cur->type != XML_CDATA_SECTION_NODE)) {
6350 delete = cur;
6351 goto skip_children;
6352 }
6353
6354 /*
6355 * Skip to next node
6356 */
6357 if (cur->children != NULL) {
6358 if ((cur->children->type != XML_ENTITY_DECL) &&
6359 (cur->children->type != XML_ENTITY_REF_NODE) &&
6360 (cur->children->type != XML_ENTITY_NODE)) {
6361 cur = cur->children;
6362 continue;
6363 }
6364 }
6365 skip_children:
6366 if (cur->next != NULL) {
6367 cur = cur->next;
6368 continue;
6369 }
6370
6371 do {
6372 cur = cur->parent;
6373 if (cur == NULL)
6374 break;
6375 if (cur == root) {
6376 cur = NULL;
6377 break;
6378 }
6379 if (cur->next != NULL) {
6380 cur = cur->next;
6381 break;
6382 }
6383 } while (cur != NULL);
6384 }
6385 if (delete != NULL) {
6386 xmlUnlinkNode(delete);
6387 xmlFreeNode(delete);
6388 delete = NULL;
6389 }
6390}
6391
William M. Brack2f2a6632004-08-20 23:09:47 +00006392
6393/**
6394 * xmlSchemaImportSchema
6395 *
6396 * @ctxt: a schema validation context
6397 * @schemaLocation: an URI defining where to find the imported schema
6398 *
6399 * import a XML schema
6400 * *WARNING* this interface is highly subject to change
6401 *
6402 * Returns -1 in case of error and 1 in case of success.
6403 */
6404#if 0
6405static xmlSchemaImportPtr
6406xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6407 const xmlChar *schemaLocation)
6408{
6409 xmlSchemaImportPtr import;
6410 xmlSchemaParserCtxtPtr newctxt;
6411
6412 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6413 if (newctxt == NULL) {
6414 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6415 NULL);
6416 return (NULL);
6417 }
6418 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6419 /* Keep the same dictionnary for parsing, really */
6420 xmlDictReference(ctxt->dict);
6421 newctxt->dict = ctxt->dict;
6422 newctxt->includes = 0;
6423 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6424
6425 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6426 ctxt->userData);
6427
6428 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6429 if (import == NULL) {
6430 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6431 NULL);
6432 xmlSchemaFreeParserCtxt(newctxt);
6433 return (NULL);
6434 }
6435
6436 memset(import, 0, sizeof(xmlSchemaImport));
6437 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6438 import->schema = xmlSchemaParse(newctxt);
6439
6440 if (import->schema == NULL) {
6441 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006442 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006443 "Failed to import schema from location \"%s\".\n",
6444 schemaLocation, NULL);
6445
6446 xmlSchemaFreeParserCtxt(newctxt);
6447 /* The schemaLocation is held by the dictionary.
6448 if (import->schemaLocation != NULL)
6449 xmlFree((xmlChar *)import->schemaLocation);
6450 */
6451 xmlFree(import);
6452 return NULL;
6453 }
6454
6455 xmlSchemaFreeParserCtxt(newctxt);
6456 return import;
6457}
6458#endif
6459
6460static void
6461xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6462{
6463 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6464 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6465
6466 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6467 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6468
6469 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6470 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6471 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6472 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6473 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6474 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6475 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6476 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6477
6478 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6479 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6480 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6481 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6482 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6483 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6484}
6485
6486static void
6487xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6488 xmlSchemaPtr schema,
6489 xmlNodePtr node)
6490{
6491 xmlAttrPtr attr;
6492 const xmlChar *val;
6493
6494 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6495 if (attr != NULL) {
6496 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6497 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6498 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6499 xmlSchemaPSimpleTypeErr(ctxt,
6500 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6501 NULL, NULL, (xmlNodePtr) attr, NULL,
6502 "(qualified | unqualified)", val, NULL, NULL, NULL);
6503 }
6504 }
6505
6506 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6507 if (attr != NULL) {
6508 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6509 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6510 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6511 xmlSchemaPSimpleTypeErr(ctxt,
6512 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6513 NULL, NULL, (xmlNodePtr) attr, NULL,
6514 "(qualified | unqualified)", val, NULL, NULL, NULL);
6515 }
6516 }
6517
6518 attr = xmlSchemaGetPropNode(node, "finalDefault");
6519 if (attr != NULL) {
6520 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6521 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6522 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6523 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6524 -1,
6525 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6526 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6527 xmlSchemaPSimpleTypeErr(ctxt,
6528 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6529 NULL, NULL, (xmlNodePtr) attr, NULL,
6530 "(#all | List of (extension | restriction | list | union))",
6531 val, NULL, NULL, NULL);
6532 }
6533 }
6534
6535 attr = xmlSchemaGetPropNode(node, "blockDefault");
6536 if (attr != NULL) {
6537 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6538 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6539 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6540 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6541 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6542 xmlSchemaPSimpleTypeErr(ctxt,
6543 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6544 NULL, NULL, (xmlNodePtr) attr, NULL,
6545 "(#all | List of (extension | restriction | substitution))",
6546 val, NULL, NULL, NULL);
6547 }
6548 }
6549}
6550
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006551/**
6552 * xmlSchemaParseSchemaTopLevel:
6553 * @ctxt: a schema validation context
6554 * @schema: the schemas
6555 * @nodes: the list of top level nodes
6556 *
6557 * Returns the internal XML Schema structure built from the resource or
6558 * NULL in case of error
6559 */
6560static void
6561xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6562 xmlSchemaPtr schema, xmlNodePtr nodes)
6563{
6564 xmlNodePtr child;
6565 xmlSchemaAnnotPtr annot;
6566
6567 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6568 return;
6569
6570 child = nodes;
6571 while ((IS_SCHEMA(child, "include")) ||
6572 (IS_SCHEMA(child, "import")) ||
6573 (IS_SCHEMA(child, "redefine")) ||
6574 (IS_SCHEMA(child, "annotation"))) {
6575 if (IS_SCHEMA(child, "annotation")) {
6576 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6577 if (schema->annot == NULL)
6578 schema->annot = annot;
6579 else
6580 xmlSchemaFreeAnnot(annot);
6581 } else if (IS_SCHEMA(child, "import")) {
6582 xmlSchemaParseImport(ctxt, schema, child);
6583 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006584 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006585 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006586 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006587 } else if (IS_SCHEMA(child, "redefine")) {
6588 TODO
6589 }
6590 child = child->next;
6591 }
6592 while (child != NULL) {
6593 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006594 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006595 child = child->next;
6596 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006597 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006598 child = child->next;
6599 } else if (IS_SCHEMA(child, "element")) {
6600 xmlSchemaParseElement(ctxt, schema, child, 1);
6601 child = child->next;
6602 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006603 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006604 child = child->next;
6605 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006606 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006607 child = child->next;
6608 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006609 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006610 child = child->next;
6611 } else if (IS_SCHEMA(child, "notation")) {
6612 xmlSchemaParseNotation(ctxt, schema, child);
6613 child = child->next;
6614 } else {
6615 xmlSchemaPErr2(ctxt, NULL, child,
6616 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006617 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006618 child->name, NULL);
6619 child = child->next;
6620 }
6621 while (IS_SCHEMA(child, "annotation")) {
6622 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6623 if (schema->annot == NULL)
6624 schema->annot = annot;
6625 else
6626 xmlSchemaFreeAnnot(annot);
6627 child = child->next;
6628 }
6629 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006630 ctxt->parentItem = NULL;
6631 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006632}
6633
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006634static xmlSchemaImportPtr
6635xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6636 xmlHashTablePtr *imports,
6637 const xmlChar *nsName)
6638{
6639 xmlSchemaImportPtr ret;
6640
6641 if (*imports == NULL) {
6642 *imports = xmlHashCreate(10);
6643 if (*imports == NULL) {
6644 xmlSchemaPCustomErr(ctxt,
6645 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6646 NULL, NULL, (xmlNodePtr) ctxt->doc,
6647 "Internal error: failed to build the import table",
6648 NULL);
6649 return (NULL);
6650 }
6651 }
6652 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6653 if (ret == NULL) {
6654 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6655 return (NULL);
6656 }
6657 memset(ret, 0, sizeof(xmlSchemaImport));
6658 if (nsName == NULL)
6659 nsName = XML_SCHEMAS_NO_NAMESPACE;
6660 xmlHashAddEntry(*imports, nsName, ret);
6661
6662 return (ret);
6663}
6664
6665static int
6666xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006667 xmlSchemaPtr schema,
6668 xmlNodePtr node,
6669 const xmlChar *nsName,
6670 const xmlChar *location,
6671 xmlDocPtr *doc,
6672 const xmlChar **targetNamespace,
6673 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006674{
6675 xmlParserCtxtPtr parserCtxt;
6676 xmlSchemaImportPtr import;
6677 const xmlChar *ns;
6678 xmlNodePtr root;
6679
6680 /*
6681 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6682 * <xsi:noNamespaceSchemaLocation>.
6683 */
6684 *doc = NULL;
6685 /*
6686 * Given that the schemaLocation [attribute] is only a hint, it is open
6687 * to applications to ignore all but the first <import> for a given
6688 * namespace, regardless of the ·actual value· of schemaLocation, but
6689 * such a strategy risks missing useful information when new
6690 * schemaLocations are offered.
6691 *
6692 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6693 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6694 * valid or not.
6695 * We will follow XSV here.
6696 */
6697 if (location == NULL) {
6698 /*
6699 * Schema Document Location Strategy:
6700 *
6701 * 3 Based on the namespace name, identify an existing schema document,
6702 * either as a resource which is an XML document or a <schema> element
6703 * information item, in some local schema repository;
6704 *
6705 * 5 Attempt to resolve the namespace name to locate such a resource.
6706 *
6707 * NOTE: Those stategies are not supported, so we will skip.
6708 */
6709 return (0);
6710 }
6711 if (nsName == NULL)
6712 ns = XML_SCHEMAS_NO_NAMESPACE;
6713 else
6714 ns = nsName;
6715
6716 import = xmlHashLookup(schema->schemasImports, ns);
6717 if (import != NULL) {
6718 /*
6719 * There was a valid resource for the specified namespace already
6720 * defined, so skip.
6721 * TODO: This might be changed someday to allow import of
6722 * components from multiple documents for a single target namespace.
6723 */
6724 return (0);
6725 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006726
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006727 /*
6728 * Schema Document Location Strategy:
6729 *
6730 * 2 Based on the location URI, identify an existing schema document,
6731 * either as a resource which is an XML document or a <schema> element
6732 * information item, in some local schema repository;
6733 *
6734 * 4 Attempt to resolve the location URI, to locate a resource on the
6735 * web which is or contains or references a <schema> element;
6736 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6737 *
6738 */
6739 if ((absolute == 0) && (node != NULL)) {
6740 xmlChar *base, *URI;
6741
6742 base = xmlNodeGetBase(node->doc, node);
6743 if (base == NULL) {
6744 URI = xmlBuildURI(location, node->doc->URL);
6745 } else {
6746 URI = xmlBuildURI(location, base);
6747 xmlFree(base);
6748 }
6749 if (URI != NULL) {
6750 location = xmlDictLookup(ctxt->dict, URI, -1);
6751 xmlFree(URI);
6752 }
6753 }
6754 parserCtxt = xmlNewParserCtxt();
6755 if (parserCtxt == NULL) {
6756 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6757 "allocating a parser context", NULL);
6758 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00006759 }
6760
6761 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
6762 xmlDictFree(parserCtxt->dict);
6763 parserCtxt->dict = ctxt->dict;
6764 xmlDictReference(parserCtxt->dict);
6765 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006766
6767 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6768 NULL, SCHEMAS_PARSE_OPTIONS);
6769
6770 /*
6771 * 2.1 The referent is (a fragment of) a resource which is an
6772 * XML document (see clause 1.1), which in turn corresponds to
6773 * a <schema> element information item in a well-formed information
6774 * set, which in turn corresponds to a valid schema.
6775 * TODO: What to do with the "fragment" stuff?
6776 *
6777 * 2.2 The referent is a <schema> element information item in
6778 * a well-formed information set, which in turn corresponds
6779 * to a valid schema.
6780 * NOTE: 2.2 won't apply, since only XML documents will be processed
6781 * here.
6782 */
6783 if (*doc == NULL) {
6784 xmlErrorPtr lerr;
6785 /*
6786 * It is *not* an error for the application schema reference
6787 * strategy to fail.
6788 *
6789 * If the doc is NULL and the parser error is an IO error we
6790 * will assume that the resource could not be located or accessed.
6791 *
6792 * TODO: Try to find specific error codes to react only on
6793 * localisation failures.
6794 *
6795 * TODO, FIXME: Check the spec: is a namespace added to the imported
6796 * namespaces, even if the schemaLocation did not provide
6797 * a resource? I guess so, since omitting the "schemaLocation"
6798 * attribute, imports a namespace as well.
6799 */
6800 lerr = xmlGetLastError();
6801 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6802 xmlFreeParserCtxt(parserCtxt);
6803 return(0);
6804 }
6805
6806 xmlSchemaPCustomErr(ctxt,
6807 XML_SCHEMAP_SRC_IMPORT_2_1,
6808 NULL, NULL, node,
6809 "Failed to parse the resource '%s' for import",
6810 location);
6811 xmlFreeParserCtxt(parserCtxt);
6812 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6813 }
6814 xmlFreeParserCtxt(parserCtxt);
6815
6816 root = xmlDocGetRootElement(*doc);
6817 if (root == NULL) {
6818 xmlSchemaPCustomErr(ctxt,
6819 XML_SCHEMAP_SRC_IMPORT_2_1,
6820 NULL, NULL, node,
6821 "The XML document '%s' to be imported has no document "
6822 "element", location);
6823 xmlFreeDoc(*doc);
6824 *doc = NULL;
6825 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6826 }
6827
6828 xmlSchemaCleanupDoc(ctxt, root);
6829
6830 if (!IS_SCHEMA(root, "schema")) {
6831 xmlSchemaPCustomErr(ctxt,
6832 XML_SCHEMAP_SRC_IMPORT_2_1,
6833 NULL, NULL, node,
6834 "The XML document '%s' to be imported is not a XML schema document",
6835 location);
6836 xmlFreeDoc(*doc);
6837 *doc = NULL;
6838 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6839 }
6840 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6841 /*
6842 * Schema Representation Constraint: Import Constraints and Semantics
6843 */
6844 if (nsName == NULL) {
6845 if (*targetNamespace != NULL) {
6846 xmlSchemaPCustomErr(ctxt,
6847 XML_SCHEMAP_SRC_IMPORT_3_2,
6848 NULL, NULL, node,
6849 "The XML schema to be imported is not expected "
6850 "to have a target namespace; this differs from "
6851 "its target namespace of '%s'", *targetNamespace);
6852 xmlFreeDoc(*doc);
6853 *doc = NULL;
6854 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6855 }
6856 } else {
6857 if (*targetNamespace == NULL) {
6858 xmlSchemaPCustomErr(ctxt,
6859 XML_SCHEMAP_SRC_IMPORT_3_1,
6860 NULL, NULL, node,
6861 "The XML schema to be imported is expected to have a target "
6862 "namespace of '%s'", nsName);
6863 xmlFreeDoc(*doc);
6864 *doc = NULL;
6865 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6866 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6867 xmlSchemaPCustomErrExt(ctxt,
6868 XML_SCHEMAP_SRC_IMPORT_3_1,
6869 NULL, NULL, node,
6870 "The XML schema to be imported is expected to have a "
6871 "target namespace of '%s'; this differs from "
6872 "its target namespace of '%s'",
6873 nsName, *targetNamespace, NULL);
6874 xmlFreeDoc(*doc);
6875 *doc = NULL;
6876 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6877 }
6878 }
6879
6880 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6881 if (import == NULL) {
6882 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6883 NULL, NULL, NULL,
6884 "Internal error: xmlSchemaAcquireSchemaDoc, "
6885 "failed to build import table", NULL);
6886 xmlFreeDoc(*doc);
6887 *doc = NULL;
6888 return (-1);
6889 }
6890 import->schemaLocation = location;
6891 import->doc = *doc;
6892 return (0);
6893}
William M. Brack2f2a6632004-08-20 23:09:47 +00006894
6895/**
6896 * xmlSchemaParseImport:
6897 * @ctxt: a schema validation context
6898 * @schema: the schema being built
6899 * @node: a subtree containing XML Schema informations
6900 *
6901 * parse a XML schema Import definition
6902 * *WARNING* this interface is highly subject to change
6903 *
6904 * Returns 0 in case of success, a positive error code if
6905 * not valid and -1 in case of an internal error.
6906 */
6907static int
6908xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6909 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006910{
6911 xmlNodePtr child;
6912 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006913 const xmlChar *schemaLocation = NULL;
6914 const xmlChar *targetNamespace, *oldTNS, *url;
6915 xmlAttrPtr attr;
6916 xmlDocPtr doc;
6917 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006918 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006919
6920
6921 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6922 return (-1);
6923
6924 /*
6925 * Check for illegal attributes.
6926 */
6927 attr = node->properties;
6928 while (attr != NULL) {
6929 if (attr->ns == NULL) {
6930 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6931 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6932 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6933 xmlSchemaPIllegalAttrErr(ctxt,
6934 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6935 NULL, NULL, attr);
6936 }
6937 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6938 xmlSchemaPIllegalAttrErr(ctxt,
6939 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6940 NULL, NULL, attr);
6941 }
6942 attr = attr->next;
6943 }
6944 /*
6945 * Extract and validate attributes.
6946 */
6947 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6948 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6949 &namespace) != 0) {
6950 xmlSchemaPSimpleTypeErr(ctxt,
6951 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6952 NULL, NULL, node,
6953 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6954 NULL, namespace, NULL, NULL, NULL);
6955 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6956 }
6957
6958 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6959 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6960 &schemaLocation) != 0) {
6961 xmlSchemaPSimpleTypeErr(ctxt,
6962 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6963 NULL, NULL, node,
6964 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6965 NULL, namespace, NULL, NULL, NULL);
6966 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6967 }
6968 /*
6969 * And now for the children...
6970 */
6971 child = node->children;
6972 if (IS_SCHEMA(child, "annotation")) {
6973 /*
6974 * the annotation here is simply discarded ...
6975 */
6976 child = child->next;
6977 }
6978 if (child != NULL) {
6979 xmlSchemaPContentErr(ctxt,
6980 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6981 NULL, NULL, node, child, NULL,
6982 "(annotation?)");
6983 }
6984 /*
6985 * Apply additional constraints.
6986 */
6987 if (namespace != NULL) {
6988 /*
6989 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6990 * must not match the ·actual value· of the enclosing <schema>'s
6991 * targetNamespace [attribute].
6992 */
6993 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6994 xmlSchemaPCustomErr(ctxt,
6995 XML_SCHEMAP_SRC_IMPORT_1_1,
6996 NULL, NULL, node,
6997 "The value of the attribute 'namespace' must not match "
6998 "the target namespace '%s' of the importing schema",
6999 schema->targetNamespace);
7000 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7001 }
7002 } else {
7003 /*
7004 * 1.2 If the namespace [attribute] is not present, then the enclosing
7005 * <schema> must have a targetNamespace [attribute].
7006 */
7007 if (schema->targetNamespace == NULL) {
7008 xmlSchemaPCustomErr(ctxt,
7009 XML_SCHEMAP_SRC_IMPORT_1_2,
7010 NULL, NULL, node,
7011 "The attribute 'namespace' must be existent if "
7012 "the importing schema has no target namespace",
7013 NULL);
7014 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7015 }
7016 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007017 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007018 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007019 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007020 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7021 schemaLocation, &doc, &targetNamespace, 0);
7022 if (ret != 0) {
7023 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007024 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007025 return (ret);
7026 } else if (doc != NULL) {
7027 /*
7028 * Save and reset the context & schema.
7029 */
7030 url = ctxt->URL;
7031 /* TODO: Is using the doc->URL here correct? */
7032 ctxt->URL = doc->URL;
7033 flags = schema->flags;
7034 oldTNS = schema->targetNamespace;
7035 /*
7036 * Parse the schema.
7037 */
7038 root = xmlDocGetRootElement(doc);
7039 xmlSchemaClearSchemaDefaults(schema);
7040 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7041 schema->targetNamespace = targetNamespace;
7042 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7043 /*
7044 * Restore the context & schema.
7045 */
7046 schema->flags = flags;
7047 schema->targetNamespace = oldTNS;
7048 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007049 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007050
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007051 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007052}
7053
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007054/**
7055 * xmlSchemaParseInclude:
7056 * @ctxt: a schema validation context
7057 * @schema: the schema being built
7058 * @node: a subtree containing XML Schema informations
7059 *
7060 * parse a XML schema Include definition
7061 *
William M. Bracke7091952004-05-11 15:09:58 +00007062 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007063 * 1 in case of success.
7064 */
7065static int
7066xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7067 xmlNodePtr node)
7068{
7069 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007070 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007071 xmlDocPtr doc;
7072 xmlNodePtr root;
7073 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007074 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007075 xmlAttrPtr attr;
7076 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007077 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007078
7079
7080 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7081 return (-1);
7082
7083 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007084 * Check for illegal attributes.
7085 */
7086 attr = node->properties;
7087 while (attr != NULL) {
7088 if (attr->ns == NULL) {
7089 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7090 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7091 xmlSchemaPIllegalAttrErr(ctxt,
7092 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7093 NULL, NULL, attr);
7094 }
7095 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7096 xmlSchemaPIllegalAttrErr(ctxt,
7097 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7098 NULL, NULL, attr);
7099 }
7100 attr = attr->next;
7101 }
7102 /*
7103 * Extract and validate attributes.
7104 */
7105 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007106 * Preliminary step, extract the URI-Reference for the include and
7107 * make an URI from the base.
7108 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007109 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7110 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007111 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007112 xmlChar *uri = NULL;
7113
7114 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7115 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7116 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007117 base = xmlNodeGetBase(node->doc, node);
7118 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007119 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007120 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007121 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007122 xmlFree(base);
7123 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007124 if (uri != NULL) {
7125 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7126 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007127 }
7128 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007129 xmlSchemaPMissingAttrErr(ctxt,
7130 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7131 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007132 return (-1);
7133 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007134 /*
7135 * And now for the children...
7136 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007137 child = node->children;
7138 while (IS_SCHEMA(child, "annotation")) {
7139 /*
7140 * the annotations here are simply discarded ...
7141 */
7142 child = child->next;
7143 }
7144 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007145 xmlSchemaPContentErr(ctxt,
7146 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7147 NULL, NULL, node, child, NULL,
7148 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007149 }
7150
7151 /*
7152 * First step is to parse the input document into an DOM/Infoset
7153 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007154 /*
7155 * TODO: Use xmlCtxtReadFile to share the dictionary.
7156 */
7157 parserCtxt = xmlNewParserCtxt();
7158 if (parserCtxt == NULL) {
7159 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7160 "allocating a parser context", NULL);
7161 return(-1);
7162 }
7163
7164 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7165 xmlDictFree(parserCtxt->dict);
7166 parserCtxt->dict = ctxt->dict;
7167 xmlDictReference(parserCtxt->dict);
7168 }
7169
7170 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7171 NULL, SCHEMAS_PARSE_OPTIONS);
7172 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007173 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007174 /*
7175 * TODO: It is not an error for the ·actual value· of the
7176 * schemaLocation [attribute] to fail to resolve it all, in which
7177 * case no corresponding inclusion is performed.
7178 * So do we need a warning report here?
7179 */
7180 xmlSchemaPCustomErr(ctxt,
7181 XML_SCHEMAP_FAILED_LOAD,
7182 NULL, NULL, node,
7183 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007184 return(-1);
7185 }
7186
7187 /*
7188 * Then extract the root of the schema
7189 */
7190 root = xmlDocGetRootElement(doc);
7191 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007192 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007193 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007194 NULL, NULL, node,
7195 "The included document '%s' has no document "
7196 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007197 xmlFreeDoc(doc);
7198 return (-1);
7199 }
7200
7201 /*
7202 * Remove all the blank text nodes
7203 */
7204 xmlSchemaCleanupDoc(ctxt, root);
7205
7206 /*
7207 * Check the schemas top level element
7208 */
7209 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007210 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007211 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007212 NULL, NULL, node,
7213 "The document '%s' to be included is not a schema document",
7214 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007215 xmlFreeDoc(doc);
7216 return (-1);
7217 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007218
William M. Brack2f2a6632004-08-20 23:09:47 +00007219 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007220 /*
7221 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7222 * value· is identical to the ·actual value· of the targetNamespace
7223 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7224 */
7225 if (targetNamespace != NULL) {
7226 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007227 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007228 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007229 NULL, NULL, node,
7230 "The target namespace of the included schema "
7231 "'%s' has to be absent, since the including schema "
7232 "has no target namespace",
7233 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007234 xmlFreeDoc(doc);
7235 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007236 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7237 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007238 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007239 NULL, NULL, node,
7240 "The target namespace '%s' of the included schema '%s' "
7241 "differs from '%s' of the including schema",
7242 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007243 xmlFreeDoc(doc);
7244 return (-1);
7245 }
7246 } else if (schema->targetNamespace != NULL) {
7247 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7248 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7249 } else
7250 wasConvertingNs = 1;
7251 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007252 /*
7253 * register the include
7254 */
7255 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7256 if (include == NULL) {
7257 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7258 xmlFreeDoc(doc);
7259 return (-1);
7260 }
7261
7262 memset(include, 0, sizeof(xmlSchemaInclude));
7263 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7264 include->doc = doc;
7265 include->next = schema->includes;
7266 schema->includes = include;
7267
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007268 /*
7269 * parse the declarations in the included file like if they
7270 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007271 */
7272 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007273 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007274 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007275 /*
7276 * The default values ("blockDefault", "elementFormDefault", etc.)
7277 * are set to the values of the included schema and restored afterwards.
7278 */
7279 saveFlags = schema->flags;
7280 xmlSchemaClearSchemaDefaults(schema);
7281 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007282 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007283 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007284 /*
7285 * Remove the converting flag.
7286 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007287 if ((wasConvertingNs == 0) &&
7288 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007289 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007290 return (1);
7291}
7292
7293/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007294 * xmlSchemaParseChoice:
7295 * @ctxt: a schema validation context
7296 * @schema: the schema being built
7297 * @node: a subtree containing XML Schema informations
7298 *
7299 * parse a XML schema Choice definition
7300 * *WARNING* this interface is highly subject to change
7301 *
William M. Bracke7091952004-05-11 15:09:58 +00007302 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007303 * 1 in case of success.
7304 */
7305static xmlSchemaTypePtr
7306xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007307 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007308{
7309 xmlSchemaTypePtr type, subtype, last = NULL;
7310 xmlNodePtr child = NULL;
7311 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007312 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007313 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007314
7315 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7316 return (NULL);
7317
7318
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007319 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007320 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007321 if (type == NULL)
7322 return (NULL);
7323 type->node = node;
7324 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007325 /*
7326 * Check for illegal attributes.
7327 */
7328 attr = node->properties;
7329 while (attr != NULL) {
7330 if (attr->ns == NULL) {
7331 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7332 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7333 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7334 xmlSchemaPIllegalAttrErr(ctxt,
7335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7336 NULL, type, attr);
7337 }
7338 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7339 xmlSchemaPIllegalAttrErr(ctxt,
7340 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7341 NULL, type, attr);
7342 }
7343 attr = attr->next;
7344 }
7345 /*
7346 * Extract and validate attributes.
7347 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007348 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007349 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7350 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7351 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007352 /*
7353 * And now for the children...
7354 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007355 oldcontainer = ctxt->container;
7356 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007357 child = node->children;
7358 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007359 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7360 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007361 }
7362 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007363 (IS_SCHEMA(child, "group")) ||
7364 (IS_SCHEMA(child, "any")) ||
7365 (IS_SCHEMA(child, "choice")) ||
7366 (IS_SCHEMA(child, "sequence"))) {
7367 subtype = NULL;
7368 if (IS_SCHEMA(child, "element")) {
7369 subtype = (xmlSchemaTypePtr)
7370 xmlSchemaParseElement(ctxt, schema, child, 0);
7371 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007372 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007373 } else if (IS_SCHEMA(child, "any")) {
7374 subtype = xmlSchemaParseAny(ctxt, schema, child);
7375 } else if (IS_SCHEMA(child, "sequence")) {
7376 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7377 } else if (IS_SCHEMA(child, "choice")) {
7378 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7379 }
7380 if (subtype != NULL) {
7381 if (last == NULL) {
7382 type->subtypes = subtype;
7383 last = subtype;
7384 } else {
7385 last->next = subtype;
7386 last = subtype;
7387 }
7388 last->next = NULL;
7389 }
7390 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007391 }
7392 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007393 /* TODO: error code. */
7394 xmlSchemaPContentErr(ctxt,
7395 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7396 NULL, type, node, child, NULL,
7397 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007398 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007399 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007400 return (type);
7401}
7402
7403/**
7404 * xmlSchemaParseSequence:
7405 * @ctxt: a schema validation context
7406 * @schema: the schema being built
7407 * @node: a subtree containing XML Schema informations
7408 *
7409 * parse a XML schema Sequence definition
7410 * *WARNING* this interface is highly subject to change
7411 *
William M. Bracke7091952004-05-11 15:09:58 +00007412 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007413 * 1 in case of success.
7414 */
7415static xmlSchemaTypePtr
7416xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007417 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007418{
7419 xmlSchemaTypePtr type, subtype, last = NULL;
7420 xmlNodePtr child = NULL;
7421 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007422 xmlAttrPtr attr;
7423 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007424
7425 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7426 return (NULL);
7427
William M. Brack2f2a6632004-08-20 23:09:47 +00007428 oldcontainer = ctxt->container;
7429 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7430 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007431 if (type == NULL)
7432 return (NULL);
7433 type->node = node;
7434 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007435 /*
7436 * Check for illegal attributes.
7437 */
7438 attr = node->properties;
7439 while (attr != NULL) {
7440 if (attr->ns == NULL) {
7441 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7442 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7443 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7444 xmlSchemaPIllegalAttrErr(ctxt,
7445 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7446 NULL, type, attr);
7447 }
7448 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7449 xmlSchemaPIllegalAttrErr(ctxt,
7450 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7451 NULL, type, attr);
7452 }
7453 attr = attr->next;
7454 }
7455 /*
7456 * Extract and validate attributes.
7457 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007458 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007459 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7460 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7461 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007462 /*
7463 * And now for the children...
7464 */
7465 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007466 child = node->children;
7467 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007468 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7469 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007470 }
7471 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007472 (IS_SCHEMA(child, "group")) ||
7473 (IS_SCHEMA(child, "any")) ||
7474 (IS_SCHEMA(child, "choice")) ||
7475 (IS_SCHEMA(child, "sequence"))) {
7476 subtype = NULL;
7477 if (IS_SCHEMA(child, "element")) {
7478 subtype = (xmlSchemaTypePtr)
7479 xmlSchemaParseElement(ctxt, schema, child, 0);
7480 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007481 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007482 } else if (IS_SCHEMA(child, "any")) {
7483 subtype = xmlSchemaParseAny(ctxt, schema, child);
7484 } else if (IS_SCHEMA(child, "choice")) {
7485 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7486 } else if (IS_SCHEMA(child, "sequence")) {
7487 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7488 }
7489 if (subtype != NULL) {
7490 if (last == NULL) {
7491 type->subtypes = subtype;
7492 last = subtype;
7493 } else {
7494 last->next = subtype;
7495 last = subtype;
7496 }
7497 last->next = NULL;
7498 }
7499 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007500 }
7501 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007502 xmlSchemaPContentErr(ctxt,
7503 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7504 NULL, type, node, child, NULL,
7505 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007506 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007507 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007508
7509 return (type);
7510}
7511
7512/**
7513 * xmlSchemaParseRestriction:
7514 * @ctxt: a schema validation context
7515 * @schema: the schema being built
7516 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007517 *
7518 * parse a XML schema Restriction definition
7519 * *WARNING* this interface is highly subject to change
7520 *
7521 * Returns the type definition or NULL in case of error
7522 */
7523static xmlSchemaTypePtr
7524xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007525 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007526{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007527 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007528 xmlNodePtr child = NULL;
7529 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007530 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007531 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007532
7533 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7534 return (NULL);
7535
7536 oldcontainer = ctxt->container;
7537
William M. Brack2f2a6632004-08-20 23:09:47 +00007538 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7539 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007540 if (type == NULL)
7541 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007542 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007543 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007544 /*
7545 * Check for illegal attributes.
7546 */
7547 attr = node->properties;
7548 while (attr != NULL) {
7549 if (attr->ns == NULL) {
7550 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7551 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7552 xmlSchemaPIllegalAttrErr(ctxt,
7553 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7554 NULL, type, attr);
7555 }
7556 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7557 xmlSchemaPIllegalAttrErr(ctxt,
7558 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7559 NULL, type, attr);
7560 }
7561 attr = attr->next;
7562 }
7563 /*
7564 * Extract and validate attributes.
7565 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007566 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007567 /*
7568 * Attribute "base".
7569 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007570 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007571 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007572 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7573 /* TODO: Think about the error code. */
7574 xmlSchemaPMissingAttrErr(ctxt,
7575 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7576 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007577 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007578 /*
7579 * And now for the children...
7580 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007581 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007582 child = node->children;
7583 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007584 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7585 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007586 }
7587 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007588 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7589 if (IS_SCHEMA(child, "all")) {
7590 subtype = (xmlSchemaTypePtr)
7591 xmlSchemaParseAll(ctxt, schema, child);
7592 child = child->next;
7593 type->subtypes = subtype;
7594 } else if (IS_SCHEMA(child, "choice")) {
7595 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7596 child = child->next;
7597 type->subtypes = subtype;
7598 } else if (IS_SCHEMA(child, "sequence")) {
7599 subtype = (xmlSchemaTypePtr)
7600 xmlSchemaParseSequence(ctxt, schema, child);
7601 child = child->next;
7602 type->subtypes = subtype;
7603 } else if (IS_SCHEMA(child, "group")) {
7604 subtype = (xmlSchemaTypePtr)
7605 xmlSchemaParseGroup(ctxt, schema, child, 0);
7606 child = child->next;
7607 type->subtypes = subtype;
7608 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007609 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7610 if (IS_SCHEMA(child, "simpleType")) {
7611 if (type->base != NULL) {
7612 /*
7613 * src-restriction-base-or-simpleType
7614 * Either the base [attribute] or the simpleType [child] of the
7615 * <restriction> element must be present, but not both.
7616 */
7617 xmlSchemaPContentErr(ctxt,
7618 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7619 NULL, NULL, type->node, child,
7620 "The attribute 'base' and the <simpleType> child are "
7621 "mutually exclusive", NULL);
7622 } else {
7623 subtype = (xmlSchemaTypePtr)
7624 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7625 type->baseType = subtype;
7626 }
7627 child = child->next;
7628 }
7629 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007630 if (IS_SCHEMA(child, "simpleType")) {
7631 subtype = (xmlSchemaTypePtr)
7632 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007633 type->subtypes = subtype;
7634 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007635 }
7636 }
7637 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7638 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7639 xmlSchemaFacetPtr facet, lastfacet = NULL;
7640
Daniel Veillard01fa6152004-06-29 17:04:39 +00007641 /*
7642 * Add the facets to the parent simpleType/complexType.
7643 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007644 /*
7645 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7646 * Simple Type Definition Schema Representation Constraint:
7647 * *Single Facet Value*
7648 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007649 while ((IS_SCHEMA(child, "minInclusive")) ||
7650 (IS_SCHEMA(child, "minExclusive")) ||
7651 (IS_SCHEMA(child, "maxInclusive")) ||
7652 (IS_SCHEMA(child, "maxExclusive")) ||
7653 (IS_SCHEMA(child, "totalDigits")) ||
7654 (IS_SCHEMA(child, "fractionDigits")) ||
7655 (IS_SCHEMA(child, "pattern")) ||
7656 (IS_SCHEMA(child, "enumeration")) ||
7657 (IS_SCHEMA(child, "whiteSpace")) ||
7658 (IS_SCHEMA(child, "length")) ||
7659 (IS_SCHEMA(child, "maxLength")) ||
7660 (IS_SCHEMA(child, "minLength"))) {
7661 facet = xmlSchemaParseFacet(ctxt, schema, child);
7662 if (facet != NULL) {
7663 if (lastfacet == NULL)
7664 ctxt->ctxtType->facets = facet;
7665 else
7666 lastfacet->next = facet;
7667 lastfacet = facet;
7668 lastfacet->next = NULL;
7669 }
7670 child = child->next;
7671 }
7672 /*
7673 * Create links for derivation and validation.
7674 */
7675 if (lastfacet != NULL) {
7676 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7677
7678 facet = ctxt->ctxtType->facets;
7679 do {
7680 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7681 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007682 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007683 xmlFree(facetLink);
7684 return (NULL);
7685 }
7686 facetLink->facet = facet;
7687 facetLink->next = NULL;
7688 if (lastFacetLink == NULL)
7689 ctxt->ctxtType->facetSet = facetLink;
7690 else
7691 lastFacetLink->next = facetLink;
7692 lastFacetLink = facetLink;
7693 facet = facet->next;
7694 } while (facet != NULL);
7695 }
7696 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007697 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7698 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7699 if (IS_SCHEMA(child, "anyAttribute")) {
7700 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7701 child = child->next;
7702 }
7703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007704 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007705 /* TODO: Think about the error code. */
7706 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7707 xmlSchemaPContentErr(ctxt,
7708 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7709 NULL, type, node, child, NULL,
7710 "annotation?, (group | all | choice | sequence)?, "
7711 "((attribute | attributeGroup)*, anyAttribute?))");
7712 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7713 xmlSchemaPContentErr(ctxt,
7714 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7715 NULL, type, node, child, NULL,
7716 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7717 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7718 "length | minLength | maxLength | enumeration | whiteSpace | "
7719 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7720 } else {
7721 /* Simple type */
7722 xmlSchemaPContentErr(ctxt,
7723 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7724 NULL, type, node, child, NULL,
7725 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7726 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7727 "length | minLength | maxLength | enumeration | whiteSpace | "
7728 "pattern)*))");
7729 }
7730 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007731 ctxt->container = oldcontainer;
7732 return (type);
7733}
7734
7735/**
7736 * xmlSchemaParseExtension:
7737 * @ctxt: a schema validation context
7738 * @schema: the schema being built
7739 * @node: a subtree containing XML Schema informations
7740 *
7741 * parse a XML schema Extension definition
7742 * *WARNING* this interface is highly subject to change
7743 *
7744 * Returns the type definition or NULL in case of error
7745 */
7746static xmlSchemaTypePtr
7747xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007748 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007749{
7750 xmlSchemaTypePtr type, subtype;
7751 xmlNodePtr child = NULL;
7752 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007753 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007754
7755 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7756 return (NULL);
7757
7758 oldcontainer = ctxt->container;
7759
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007760 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007761 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007762 if (type == NULL)
7763 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007764 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007765 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007766 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007767 ctxt->container = name;
7768
7769 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7770 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007771 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007772 "<extension>: The attribute \"base\" is missing.\n",
7773 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007774 }
7775 child = node->children;
7776 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007777 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7778 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007779 }
7780 subtype = NULL;
7781
7782 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007783 subtype = xmlSchemaParseAll(ctxt, schema, child);
7784 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007785 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007786 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7787 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007788 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007789 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7790 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007791 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007792 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007793 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007794 }
7795 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007796 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007797 if ((ctxt->ctxtType != NULL) &&
7798 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7799 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7800 if (IS_SCHEMA(child, "anyAttribute")) {
7801 ctxt->ctxtType->attributeWildcard =
7802 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7803 child = child->next;
7804 }
7805 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007806 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007807 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007808 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7809 "<extension> has unexpected content.\n", type->name,
7810 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007811 }
7812 ctxt->container = oldcontainer;
7813 return (type);
7814}
7815
7816/**
7817 * xmlSchemaParseSimpleContent:
7818 * @ctxt: a schema validation context
7819 * @schema: the schema being built
7820 * @node: a subtree containing XML Schema informations
7821 *
7822 * parse a XML schema SimpleContent definition
7823 * *WARNING* this interface is highly subject to change
7824 *
7825 * Returns the type definition or NULL in case of error
7826 */
7827static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007828xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7829 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007830{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007831 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007832 xmlNodePtr child = NULL;
7833 xmlChar name[30];
7834
7835 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7836 return (NULL);
7837
William M. Bracke7091952004-05-11 15:09:58 +00007838 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007839 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007840 if (type == NULL)
7841 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007842 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007843 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007844 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007845
7846 child = node->children;
7847 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007848 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7849 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007850 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007851 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007852 ctxt->parentItem = type;
7853 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007854 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007855 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007856 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007857 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007858 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007859 subtype = (xmlSchemaTypePtr)
7860 xmlSchemaParseExtension(ctxt, schema, child);
7861 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007862 }
7863 type->subtypes = subtype;
7864 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007865 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007866 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7867 "<simpleContent> has unexpected content.\n",
7868 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007869 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007870 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007871 return (type);
7872}
7873
7874/**
7875 * xmlSchemaParseComplexContent:
7876 * @ctxt: a schema validation context
7877 * @schema: the schema being built
7878 * @node: a subtree containing XML Schema informations
7879 *
7880 * parse a XML schema ComplexContent definition
7881 * *WARNING* this interface is highly subject to change
7882 *
7883 * Returns the type definition or NULL in case of error
7884 */
7885static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007886xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7887 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007888{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007889 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007890 xmlNodePtr child = NULL;
7891 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007892 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007893
7894 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7895 return (NULL);
7896
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007897 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007898 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007899 if (type == NULL)
7900 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007901 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007902 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007903 /*
7904 * Check for illegal attributes.
7905 */
7906 attr = node->properties;
7907 while (attr != NULL) {
7908 if (attr->ns == NULL) {
7909 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7910 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7911 {
7912 xmlSchemaPIllegalAttrErr(ctxt,
7913 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7914 NULL, NULL, attr);
7915 }
7916 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7917 xmlSchemaPIllegalAttrErr(ctxt,
7918 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7919 NULL, NULL, attr);
7920 }
7921 attr = attr->next;
7922 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007923 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007924 /*
7925 * Handle attribute 'mixed'.
7926 */
7927 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7928 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7929 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7930 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007931 child = node->children;
7932 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007933 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7934 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007935 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007936 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007937 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007938 subtype = NULL;
7939 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007940 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007941 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007942 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007943 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007944 subtype = (xmlSchemaTypePtr)
7945 xmlSchemaParseExtension(ctxt, schema, child);
7946 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007947 }
7948 type->subtypes = subtype;
7949 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007950 xmlSchemaPContentErr(ctxt,
7951 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7952 NULL, NULL, node, child,
7953 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007954 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007955 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007956 return (type);
7957}
7958
7959/**
7960 * xmlSchemaParseComplexType:
7961 * @ctxt: a schema validation context
7962 * @schema: the schema being built
7963 * @node: a subtree containing XML Schema informations
7964 *
7965 * parse a XML schema Complex Type definition
7966 * *WARNING* this interface is highly subject to change
7967 *
7968 * Returns the type definition or NULL in case of error
7969 */
7970static xmlSchemaTypePtr
7971xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007972 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007973{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007974 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007975 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007976 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007977 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007978 xmlAttrPtr attr;
7979 const xmlChar *attrValue;
7980 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007981 char buf[40];
7982
Daniel Veillard4255d502002-04-16 15:50:10 +00007983
7984 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7985 return (NULL);
7986
Daniel Veillard01fa6152004-06-29 17:04:39 +00007987 ctxtType = ctxt->ctxtType;
7988
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007989 if (topLevel) {
7990 attr = xmlSchemaGetPropNode(node, "name");
7991 if (attr == NULL) {
7992 xmlSchemaPMissingAttrErr(ctxt,
7993 XML_SCHEMAP_S4S_ATTR_MISSING,
7994 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7995 "name", NULL);
7996 return (NULL);
7997 } else if (xmlSchemaPValAttrNode(ctxt,
7998 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7999 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8000 return (NULL);
8001 }
8002 }
8003
8004 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008005 /*
8006 * Parse as local complex type definition.
8007 */
8008 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
8009 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8010 if (type == NULL)
8011 return (NULL);
8012 name = (const xmlChar *) buf;
8013 type->node = node;
8014 type->type = XML_SCHEMA_TYPE_COMPLEX;
8015 /*
8016 * TODO: We need the target namespace.
8017 */
8018 } else {
8019 /*
8020 * Parse as global complex type definition.
8021 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008022 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008023 if (type == NULL)
8024 return (NULL);
8025 type->node = node;
8026 type->type = XML_SCHEMA_TYPE_COMPLEX;
8027 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8028 /*
8029 * Set defaults.
8030 */
8031 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8032 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008033 }
8034 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008035 /*
8036 * Handle attributes.
8037 */
8038 attr = node->properties;
8039 while (attr != NULL) {
8040 if (attr->ns == NULL) {
8041 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8042 /*
8043 * Attribute "id".
8044 */
8045 type->id = xmlSchemaGetProp(ctxt, node, "id");
8046 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8047 /*
8048 * Attribute "mixed".
8049 */
8050 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8051 (xmlNodePtr) attr))
8052 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8053 } else if (topLevel) {
8054 /*
8055 * Attributes of global complex type definitions.
8056 */
8057 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8058 /* Pass. */
8059 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8060 /*
8061 * Attribute "abstract".
8062 */
8063 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8064 (xmlNodePtr) attr))
8065 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8066 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8067 /*
8068 * Attribute "final".
8069 */
8070 attrValue = xmlSchemaGetNodeContent(ctxt,
8071 (xmlNodePtr) attr);
8072 if (xmlSchemaPValAttrBlockFinal(attrValue,
8073 &(type->flags),
8074 -1,
8075 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8076 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8077 -1, -1, -1) != 0)
8078 {
8079 xmlSchemaPSimpleTypeErr(ctxt,
8080 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8081 &des, type, (xmlNodePtr) attr,
8082 NULL,
8083 "(#all | List of (extension | restriction))",
8084 attrValue, NULL, NULL, NULL);
8085 }
8086 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8087 /*
8088 * Attribute "block".
8089 */
8090 attrValue = xmlSchemaGetNodeContent(ctxt,
8091 (xmlNodePtr) attr);
8092 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8093 -1,
8094 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8095 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8096 -1, -1, -1) != 0) {
8097 xmlSchemaPSimpleTypeErr(ctxt,
8098 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8099 &des, type, (xmlNodePtr) attr,
8100 NULL,
8101 "(#all | List of (extension | restriction)) ",
8102 attrValue, NULL, NULL, NULL);
8103 }
8104 } else {
8105 xmlSchemaPIllegalAttrErr(ctxt,
8106 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8107 &des, type, attr);
8108 }
8109 } else {
8110 xmlSchemaPIllegalAttrErr(ctxt,
8111 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8112 &des, type, attr);
8113 }
8114 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8115 xmlSchemaPIllegalAttrErr(ctxt,
8116 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8117 &des, type, attr);
8118 }
8119 attr = attr->next;
8120 }
8121 /*
8122 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008123 * This will be only changed if a complex type
8124 * inherits an attribute wildcard from a base type.
8125 */
8126 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008127 /*
8128 * And now for the children...
8129 */
8130 oldcontainer = ctxt->container;
8131 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008132 child = node->children;
8133 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008134 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8135 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008136 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008137 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008138 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008139 /*
8140 * 3.4.3 : 2.2
8141 * Specifying mixed='true' when the <simpleContent>
8142 * alternative is chosen has no effect
8143 */
William M. Bracke7091952004-05-11 15:09:58 +00008144 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8145 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008146 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8147 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008148 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008149 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8150 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008151 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008152 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008153 /*
8154 * Parse model groups.
8155 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008156 if (IS_SCHEMA(child, "all")) {
8157 subtype = xmlSchemaParseAll(ctxt, schema, child);
8158 child = child->next;
8159 } else if (IS_SCHEMA(child, "choice")) {
8160 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8161 child = child->next;
8162 } else if (IS_SCHEMA(child, "sequence")) {
8163 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8164 child = child->next;
8165 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008166 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008167 child = child->next;
8168 }
8169 if (subtype != NULL)
8170 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008171 /*
8172 * Parse attribute decls/refs.
8173 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008174 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008175 /*
8176 * Parse attribute wildcard.
8177 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008178 if (IS_SCHEMA(child, "anyAttribute")) {
8179 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8180 child = child->next;
8181 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008182 }
8183 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008184 xmlSchemaPContentErr(ctxt,
8185 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8186 &des, type, node, child,
8187 NULL, "(annotation?, (simpleContent | complexContent | "
8188 "((group | all | choice | sequence)?, ((attribute | "
8189 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008190 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008191 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008192 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008193 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008194 return (type);
8195}
8196
Daniel Veillard4255d502002-04-16 15:50:10 +00008197/**
8198 * xmlSchemaParseSchema:
8199 * @ctxt: a schema validation context
8200 * @node: a subtree containing XML Schema informations
8201 *
8202 * parse a XML schema definition from a node set
8203 * *WARNING* this interface is highly subject to change
8204 *
8205 * Returns the internal XML Schema structure built from the resource or
8206 * NULL in case of error
8207 */
8208static xmlSchemaPtr
8209xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8210{
8211 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008212 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008213 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008214 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008215
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008216 /*
8217 * This one is called by xmlSchemaParse only and is used if
8218 * the schema to be parsed was specified via the API; i.e. not
8219 * automatically by the validated instance document.
8220 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008221 if ((ctxt == NULL) || (node == NULL))
8222 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008223 nberrors = ctxt->nberrors;
8224 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008225 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008226 xmlSchemaImportPtr import;
8227
Daniel Veillard4255d502002-04-16 15:50:10 +00008228 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008229 if (schema == NULL)
8230 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008231 /*
8232 * Disable build of list of items.
8233 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008234 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8235 if (attr != NULL) {
8236 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8237 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8238 /*
8239 * TODO: Should we proceed with an invalid target namespace?
8240 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008241 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8242 } else {
8243 schema->targetNamespace = NULL;
8244 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008245 /*
8246 * Add the current ns name and location to the import table;
8247 * this is needed to have a consistent mechanism, regardless
8248 * if all schemata are constructed dynamically fired by the
8249 * instance or if the schema to be used was specified via
8250 * the API.
8251 */
8252 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8253 schema->targetNamespace);
8254 if (import == NULL) {
8255 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8256 NULL, NULL, (xmlNodePtr) ctxt->doc,
8257 "Internal error: xmlSchemaParseSchema, "
8258 "failed to add an import entry", NULL);
8259 xmlSchemaFree(schema);
8260 schema = NULL;
8261 return (NULL);
8262 }
8263 import->schemaLocation = ctxt->URL;
8264 /*
8265 * NOTE: We won't set the doc here, otherwise it will be freed
8266 * if the import struct is freed.
8267 * import->doc = ctxt->doc;
8268 */
8269
Daniel Veillardc0826a72004-08-10 14:17:33 +00008270 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008271 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008272 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8273 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8274
William M. Brack2f2a6632004-08-20 23:09:47 +00008275 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008276 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8277 } else {
8278 xmlDocPtr doc;
8279
8280 doc = node->doc;
8281
8282 if ((doc != NULL) && (doc->URL != NULL)) {
8283 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8284 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008285 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008286 } else {
8287 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8288 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008289 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008290 }
8291 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008292 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008293 if (ctxt->nberrors != 0) {
8294 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008295 xmlSchemaFree(schema);
8296 schema = NULL;
8297 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008298 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008299 if (schema != NULL)
8300 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008301 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008302#ifdef DEBUG
8303 if (schema == NULL)
8304 xmlGenericError(xmlGenericErrorContext,
8305 "xmlSchemaParse() failed\n");
8306#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008307 return (schema);
8308}
8309
8310/************************************************************************
8311 * *
8312 * Validating using Schemas *
8313 * *
8314 ************************************************************************/
8315
8316/************************************************************************
8317 * *
8318 * Reading/Writing Schemas *
8319 * *
8320 ************************************************************************/
8321
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008322#if 0 /* Will be enabled if it is clear what options are needed. */
8323/**
8324 * xmlSchemaParserCtxtSetOptions:
8325 * @ctxt: a schema parser context
8326 * @options: a combination of xmlSchemaParserOption
8327 *
8328 * Sets the options to be used during the parse.
8329 *
8330 * Returns 0 in case of success, -1 in case of an
8331 * API error.
8332 */
8333static int
8334xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8335 int options)
8336
8337{
8338 int i;
8339
8340 if (ctxt == NULL)
8341 return (-1);
8342 /*
8343 * WARNING: Change the start value if adding to the
8344 * xmlSchemaParseOption.
8345 */
8346 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8347 if (options & 1<<i) {
8348 return (-1);
8349 }
8350 }
8351 ctxt->options = options;
8352 return (0);
8353}
8354
8355/**
8356 * xmlSchemaValidCtxtGetOptions:
8357 * @ctxt: a schema parser context
8358 *
8359 * Returns the option combination of the parser context.
8360 */
8361static int
8362xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8363
8364{
8365 if (ctxt == NULL)
8366 return (-1);
8367 else
8368 return (ctxt->options);
8369}
8370
8371 void *curItems; /* used for dynamic addition of schemata */
8372 int nbCurItems; /* used for dynamic addition of schemata */
8373 int sizeCurItems; /* used for dynamic addition of schemata */
8374
8375#endif
8376
Daniel Veillard4255d502002-04-16 15:50:10 +00008377/**
8378 * xmlSchemaNewParserCtxt:
8379 * @URL: the location of the schema
8380 *
8381 * Create an XML Schemas parse context for that file/resource expected
8382 * to contain an XML Schemas file.
8383 *
8384 * Returns the parser context or NULL in case of error
8385 */
8386xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008387xmlSchemaNewParserCtxt(const char *URL)
8388{
Daniel Veillard4255d502002-04-16 15:50:10 +00008389 xmlSchemaParserCtxtPtr ret;
8390
8391 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008392 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008393
8394 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8395 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008396 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008397 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008398 return (NULL);
8399 }
8400 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008401 ret->dict = xmlDictCreate();
8402 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008403 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008404 return (ret);
8405}
8406
8407/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008408 * xmlSchemaNewParserCtxtUseDict:
8409 * @URL: the location of the schema
8410 * @dict: the dictionary to be used
8411 *
8412 * Create an XML Schemas parse context for that file/resource expected
8413 * to contain an XML Schemas file.
8414 *
8415 * Returns the parser context or NULL in case of error
8416 */
8417static xmlSchemaParserCtxtPtr
8418xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8419{
8420 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008421 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008422 if (URL == NULL)
8423 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008424 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008425
8426 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8427 if (ret == NULL) {
8428 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8429 NULL);
8430 return (NULL);
8431 }
8432 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8433 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008434 xmlDictReference(dict);
8435 if (URL != NULL)
8436 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008437 ret->includes = 0;
8438 return (ret);
8439}
8440
8441
8442/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008443 * xmlSchemaNewMemParserCtxt:
8444 * @buffer: a pointer to a char array containing the schemas
8445 * @size: the size of the array
8446 *
8447 * Create an XML Schemas parse context for that memory buffer expected
8448 * to contain an XML Schemas file.
8449 *
8450 * Returns the parser context or NULL in case of error
8451 */
8452xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008453xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8454{
Daniel Veillard6045c902002-10-09 21:13:59 +00008455 xmlSchemaParserCtxtPtr ret;
8456
8457 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008458 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008459
8460 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8461 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008462 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008463 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008464 return (NULL);
8465 }
8466 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8467 ret->buffer = buffer;
8468 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008469 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008470 return (ret);
8471}
8472
8473/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008474 * xmlSchemaNewDocParserCtxt:
8475 * @doc: a preparsed document tree
8476 *
8477 * Create an XML Schemas parse context for that document.
8478 * NB. The document may be modified during the parsing process.
8479 *
8480 * Returns the parser context or NULL in case of error
8481 */
8482xmlSchemaParserCtxtPtr
8483xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8484{
8485 xmlSchemaParserCtxtPtr ret;
8486
8487 if (doc == NULL)
8488 return (NULL);
8489
8490 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8491 if (ret == NULL) {
8492 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8493 NULL);
8494 return (NULL);
8495 }
8496 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8497 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008498 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008499 /* The application has responsibility for the document */
8500 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008501
8502 return (ret);
8503}
8504
8505/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008506 * xmlSchemaFreeParserCtxt:
8507 * @ctxt: the schema parser context
8508 *
8509 * Free the resources associated to the schema parser context
8510 */
8511void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008512xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8513{
Daniel Veillard4255d502002-04-16 15:50:10 +00008514 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008515 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008516 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008517 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008518 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008519 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008520 xmlFree(ctxt->assemble);
8521 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008522 if (ctxt->vctxt != NULL) {
8523 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8524 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008525 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008526 xmlFree(ctxt);
8527}
8528
8529/************************************************************************
8530 * *
8531 * Building the content models *
8532 * *
8533 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008534
Daniel Veillard4255d502002-04-16 15:50:10 +00008535/**
8536 * xmlSchemaBuildAContentModel:
8537 * @type: the schema type definition
8538 * @ctxt: the schema parser context
8539 * @name: the element name whose content is being built
8540 *
8541 * Generate the automata sequence needed for that type
8542 */
8543static void
8544xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008545 xmlSchemaParserCtxtPtr ctxt,
8546 const xmlChar * name)
8547{
Daniel Veillard4255d502002-04-16 15:50:10 +00008548 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008549 xmlGenericError(xmlGenericErrorContext,
8550 "Found unexpected type = NULL in %s content model\n",
8551 name);
8552 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008553 }
8554 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008555 case XML_SCHEMA_TYPE_ANY: {
8556 xmlAutomataStatePtr start, end;
8557 xmlSchemaWildcardPtr wild;
8558 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008559
Daniel Veillardc0826a72004-08-10 14:17:33 +00008560 wild = type->attributeWildcard;
8561
8562 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008563 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008564 "Internal error: xmlSchemaBuildAContentModel, "
8565 "no wildcard on xsd:any.\n", NULL, NULL);
8566 return;
8567 }
8568
8569 start = ctxt->state;
8570 end = xmlAutomataNewState(ctxt->am);
8571
8572 if (type->maxOccurs == 1) {
8573 if (wild->any == 1) {
8574 /*
8575 * We need to add both transitions:
8576 *
8577 * 1. the {"*", "*"} for elements in a namespace.
8578 */
8579 ctxt->state =
8580 xmlAutomataNewTransition2(ctxt->am,
8581 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8582 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8583 /*
8584 * 2. the {"*"} for elements in no namespace.
8585 */
8586 ctxt->state =
8587 xmlAutomataNewTransition2(ctxt->am,
8588 start, NULL, BAD_CAST "*", NULL, type);
8589 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8590
8591 } else if (wild->nsSet != NULL) {
8592 ns = wild->nsSet;
8593 do {
8594 ctxt->state = start;
8595 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8596 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8597 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8598 ns = ns->next;
8599 } while (ns != NULL);
8600
8601 } else if (wild->negNsSet != NULL) {
8602 xmlAutomataStatePtr deadEnd;
8603
8604 deadEnd = xmlAutomataNewState(ctxt->am);
8605 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8606 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8607 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8608 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8609 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8610 }
8611 } else {
8612 int counter;
8613 xmlAutomataStatePtr hop;
8614 int maxOccurs =
8615 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8616 int minOccurs =
8617 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8618
8619 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8620 hop = xmlAutomataNewState(ctxt->am);
8621 if (wild->any == 1) {
8622 ctxt->state =
8623 xmlAutomataNewTransition2(ctxt->am,
8624 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8625 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8626 ctxt->state =
8627 xmlAutomataNewTransition2(ctxt->am,
8628 start, NULL, BAD_CAST "*", NULL, type);
8629 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8630 } else if (wild->nsSet != NULL) {
8631 ns = wild->nsSet;
8632 do {
8633 ctxt->state =
8634 xmlAutomataNewTransition2(ctxt->am,
8635 start, NULL, BAD_CAST "*", ns->value, type);
8636 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8637 ns = ns->next;
8638 } while (ns != NULL);
8639
8640 } else if (wild->negNsSet != NULL) {
8641 xmlAutomataStatePtr deadEnd;
8642
8643 deadEnd = xmlAutomataNewState(ctxt->am);
8644 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8645 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8646 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8647 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8648 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8649 }
8650 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8651 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8652 }
8653 if (type->minOccurs == 0) {
8654 xmlAutomataNewEpsilon(ctxt->am, start, end);
8655 }
8656 ctxt->state = end;
8657 break;
8658 }
8659 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008660 xmlAutomataStatePtr oldstate;
8661 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008662
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008663 /*
8664 * IMPORTANT: This puts element declarations
8665 * (and never element decl. references) into the
8666 * automaton. This is crucial and should not be changed,
8667 * since validating functions rely now on it.
8668 */
8669 particle = (xmlSchemaElementPtr) type;
8670 if (particle->ref != NULL) {
8671 if (particle->refDecl == NULL) {
8672 /*
8673 * Skip content model creation if the reference
8674 * did not resolve to a declaration.
8675 */
8676 break;
8677 } else {
8678 /*
8679 * Referenced global element declaration.
8680 */
8681 elemDecl = particle->refDecl;
8682 }
8683 } else {
8684 /*
8685 * Anonymous element declaration.
8686 */
8687 elemDecl = particle;
8688 }
8689
8690 oldstate = ctxt->state;
8691
8692 if (particle->maxOccurs >= UNBOUNDED) {
8693 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008694 xmlAutomataStatePtr tmp;
8695 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008696
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008697 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008698 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008699 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008700 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008701 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00008702 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008703 xmlAutomataNewTransition2(ctxt->am,
8704 ctxt->state, NULL,
8705 elemDecl->name,
8706 elemDecl->targetNamespace,
8707 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008708 tmp = ctxt->state;
8709 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008710 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008711 ctxt->state =
8712 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008713 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008715 } else {
8716 ctxt->state =
8717 xmlAutomataNewTransition2(ctxt->am,
8718 ctxt->state, NULL,
8719 elemDecl->name,
8720 elemDecl->targetNamespace,
8721 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008722 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8723 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008724 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008725 /* basically an elem* */
8726 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8727 ctxt->state);
8728 }
8729 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008730 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008731 xmlAutomataStatePtr tmp;
8732 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008733
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008734 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8735 oldstate, NULL);
8736 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008737 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008738 particle->minOccurs - 1,
8739 particle->maxOccurs - 1);
8740 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8741 ctxt->state,
8742 NULL,
8743 elemDecl->name,
8744 elemDecl->targetNamespace,
8745 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008746 tmp = ctxt->state;
8747 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008748 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008749 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008750 NULL, counter);
8751 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008752 /* basically an elem? */
8753 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008754 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008755 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008756
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008757 } else {
8758 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8759 ctxt->state,
8760 NULL,
8761 elemDecl->name,
8762 elemDecl->targetNamespace,
8763 (xmlSchemaTypePtr) elemDecl);
8764 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008765 /* basically an elem? */
8766 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008767 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008768 }
8769 }
8770 break;
8771 }
8772 case XML_SCHEMA_TYPE_SEQUENCE:{
8773 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008774
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008775 /*
8776 * If max and min occurances are default (1) then
8777 * simply iterate over the subtypes
8778 */
8779 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8780 subtypes = type->subtypes;
8781 while (subtypes != NULL) {
8782 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8783 subtypes = subtypes->next;
8784 }
8785 } else {
8786 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008787
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008788 if (type->maxOccurs >= UNBOUNDED) {
8789 if (type->minOccurs > 1) {
8790 xmlAutomataStatePtr tmp;
8791 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008792
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008793 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8794 oldstate,
8795 NULL);
8796 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008797
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008798 counter = xmlAutomataNewCounter(ctxt->am,
8799 type->
8800 minOccurs - 1,
8801 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008802
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008803 subtypes = type->subtypes;
8804 while (subtypes != NULL) {
8805 xmlSchemaBuildAContentModel(subtypes, ctxt,
8806 name);
8807 subtypes = subtypes->next;
8808 }
8809 tmp = ctxt->state;
8810 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8811 oldstate, counter);
8812 ctxt->state =
8813 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8814 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008815
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008816 } else {
8817 subtypes = type->subtypes;
8818 while (subtypes != NULL) {
8819 xmlSchemaBuildAContentModel(subtypes, ctxt,
8820 name);
8821 subtypes = subtypes->next;
8822 }
8823 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8824 oldstate);
8825 if (type->minOccurs == 0) {
8826 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8827 ctxt->state);
8828 }
8829 }
8830 } else if ((type->maxOccurs > 1)
8831 || (type->minOccurs > 1)) {
8832 xmlAutomataStatePtr tmp;
8833 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008834
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008835 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8836 oldstate,
8837 NULL);
8838 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008839
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008840 counter = xmlAutomataNewCounter(ctxt->am,
8841 type->minOccurs -
8842 1,
8843 type->maxOccurs -
8844 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008845
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008846 subtypes = type->subtypes;
8847 while (subtypes != NULL) {
8848 xmlSchemaBuildAContentModel(subtypes, ctxt,
8849 name);
8850 subtypes = subtypes->next;
8851 }
8852 tmp = ctxt->state;
8853 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8854 counter);
8855 ctxt->state =
8856 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8857 counter);
8858 if (type->minOccurs == 0) {
8859 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8860 ctxt->state);
8861 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008862
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008863 } else {
8864 subtypes = type->subtypes;
8865 while (subtypes != NULL) {
8866 xmlSchemaBuildAContentModel(subtypes, ctxt,
8867 name);
8868 subtypes = subtypes->next;
8869 }
8870 if (type->minOccurs == 0) {
8871 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8872 ctxt->state);
8873 }
8874 }
8875 }
8876 break;
8877 }
8878 case XML_SCHEMA_TYPE_CHOICE:{
8879 xmlSchemaTypePtr subtypes;
8880 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008881
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008882 start = ctxt->state;
8883 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008884
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008885 /*
8886 * iterate over the subtypes and remerge the end with an
8887 * epsilon transition
8888 */
8889 if (type->maxOccurs == 1) {
8890 subtypes = type->subtypes;
8891 while (subtypes != NULL) {
8892 ctxt->state = start;
8893 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8894 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8895 subtypes = subtypes->next;
8896 }
8897 } else {
8898 int counter;
8899 xmlAutomataStatePtr hop;
8900 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8901 UNBOUNDED : type->maxOccurs - 1;
8902 int minOccurs =
8903 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008904
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008905 /*
8906 * use a counter to keep track of the number of transtions
8907 * which went through the choice.
8908 */
8909 counter =
8910 xmlAutomataNewCounter(ctxt->am, minOccurs,
8911 maxOccurs);
8912 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008914 subtypes = type->subtypes;
8915 while (subtypes != NULL) {
8916 ctxt->state = start;
8917 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8918 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8919 subtypes = subtypes->next;
8920 }
8921 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8922 counter);
8923 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8924 counter);
8925 }
8926 if (type->minOccurs == 0) {
8927 xmlAutomataNewEpsilon(ctxt->am, start, end);
8928 }
8929 ctxt->state = end;
8930 break;
8931 }
8932 case XML_SCHEMA_TYPE_ALL:{
8933 xmlAutomataStatePtr start;
8934 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008935
Daniel Veillard3646d642004-06-02 19:19:14 +00008936 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008937 int lax;
8938
8939 subtypes = type->subtypes;
8940 if (subtypes == NULL)
8941 break;
8942 start = ctxt->state;
8943 while (subtypes != NULL) {
8944 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008945 /*
8946 * the following 'if' was needed to fix bug 139897
8947 * not quite sure why it only needs to be done for
8948 * elements with a 'ref', but it seems to work ok.
8949 */
8950 if (subtypes->ref != NULL)
8951 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008952 elem = (xmlSchemaElementPtr) subtypes;
8953 /*
8954 * NOTE: The {max occurs} of all the particles in the
8955 * {particles} of the group must be 0 or 1.
8956 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008957 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008958 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8959 ctxt->state,
8960 elem->name,
8961 elem->targetNamespace,
8962 1, 1, subtypes);
8963 } else if ((elem->minOccurs == 0) &&
8964 (elem->maxOccurs == 1)) {
8965
8966 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8967 ctxt->state,
8968 elem->name,
8969 elem->targetNamespace,
8970 0,
8971 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008972 subtypes);
8973 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008974 /*
8975 * NOTE: if maxOccurs == 0 then no transition will be
8976 * created.
8977 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008978 subtypes = subtypes->next;
8979 }
8980 lax = type->minOccurs == 0;
8981 ctxt->state =
8982 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8983 lax);
8984 break;
8985 }
8986 case XML_SCHEMA_TYPE_RESTRICTION:
8987 if (type->subtypes != NULL)
8988 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8989 break;
8990 case XML_SCHEMA_TYPE_EXTENSION:
8991 if (type->baseType != NULL) {
8992 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993
8994 /*
8995 * TODO: Circular definitions will be checked at the
8996 * constraint level. So remove this when the complex type
8997 * constraints are implemented.
8998 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008999 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009000 /* TODO: Change the error code. */
9001 xmlSchemaPCustomErr(ctxt,
9002 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9003 NULL, type, type->node,
9004 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009005 return;
9006 }
9007 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009008 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009009 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009010 subtypes = type->subtypes;
9011 while (subtypes != NULL) {
9012 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9013 subtypes = subtypes->next;
9014 }
9015 } else if (type->subtypes != NULL)
9016 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9017 break;
9018 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009019 /*
9020 * Handle model group definition references.
9021 * NOTE: type->subtypes is the referenced model grop definition;
9022 * and type->subtypes->subtypes is the model group (i.e. <all> or
9023 * <choice> or <sequence>).
9024 */
9025 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9026 (type->subtypes->subtypes != NULL)) {
9027 xmlSchemaTypePtr modelGr;
9028 xmlAutomataStatePtr start, end;
9029
9030 modelGr = type->subtypes->subtypes;
9031 start = ctxt->state;
9032 end = xmlAutomataNewState(ctxt->am);
9033 if (type->maxOccurs == 1) {
9034 ctxt->state = start;
9035 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9036 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9037 } else {
9038 int counter;
9039 xmlAutomataStatePtr hop;
9040 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9041 UNBOUNDED : type->maxOccurs - 1;
9042 int minOccurs =
9043 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9044
9045 counter =
9046 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9047 hop = xmlAutomataNewState(ctxt->am);
9048 ctxt->state = start;
9049 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9050 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9051 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9052 counter);
9053 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9054 counter);
9055 }
9056 if (type->minOccurs == 0) {
9057 xmlAutomataNewEpsilon(ctxt->am, start, end);
9058 }
9059 ctxt->state = end;
9060 break;
9061 }
9062 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009063 case XML_SCHEMA_TYPE_COMPLEX:
9064 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9065 if (type->subtypes != NULL)
9066 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9067 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009068 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9069 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009070 default:
9071 xmlGenericError(xmlGenericErrorContext,
9072 "Found unexpected type %d in %s content model\n",
9073 type->type, name);
9074 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009075 }
9076}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009077
Daniel Veillard4255d502002-04-16 15:50:10 +00009078/**
9079 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009080 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009081 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009082 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009083 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009084 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009085 */
9086static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009087xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009088 xmlSchemaParserCtxtPtr ctxt,
9089 const xmlChar * name)
9090{
Daniel Veillard4255d502002-04-16 15:50:10 +00009091 xmlAutomataStatePtr start;
9092
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009093 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9094 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9095 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9096 (type->contModel != NULL))
9097 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009098
9099#ifdef DEBUG_CONTENT
9100 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009101 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009102#endif
9103
Daniel Veillard4255d502002-04-16 15:50:10 +00009104 ctxt->am = xmlNewAutomata();
9105 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009106 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009107 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009108 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009109 }
9110 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009111 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009112 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009113 type->contModel = xmlAutomataCompile(ctxt->am);
9114 if (type->contModel == NULL) {
9115 xmlSchemaPCustomErr(ctxt,
9116 XML_SCHEMAP_INTERNAL,
9117 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009118 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009119 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009120 xmlSchemaPCustomErr(ctxt,
9121 XML_SCHEMAP_NOT_DETERMINISTIC,
9122 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009123 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009124 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009125 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009126#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009127 xmlGenericError(xmlGenericErrorContext,
9128 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009129 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009130#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009131 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009132 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009133 xmlFreeAutomata(ctxt->am);
9134 ctxt->am = NULL;
9135}
9136
9137/**
9138 * xmlSchemaRefFixupCallback:
9139 * @elem: the schema element context
9140 * @ctxt: the schema parser context
9141 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009142 * Resolves the references of an element declaration
9143 * or particle, which has an element declaration as it's
9144 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009145 */
9146static void
9147xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009148 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009149 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009150 const xmlChar * context ATTRIBUTE_UNUSED,
9151 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009152{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009153 if ((ctxt == NULL) || (elem == NULL) ||
9154 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009155 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009156 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009157 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009158 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009159
Daniel Veillardc0826a72004-08-10 14:17:33 +00009160 /*
9161 * TODO: Evaluate, what errors could occur if the declaration is not
9162 * found. It might be possible that the "typefixup" might crash if
9163 * no ref declaration was found.
9164 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009165 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009166 if (elemDecl == NULL) {
9167 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009168 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009169 NULL, (xmlSchemaTypePtr) elem, elem->node,
9170 "ref", elem->ref, elem->refNs,
9171 XML_SCHEMA_TYPE_ELEMENT, NULL);
9172 } else
9173 elem->refDecl = elemDecl;
9174 } else {
9175 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9176 xmlSchemaTypePtr type;
9177
9178 /* (type definition) ... otherwise the type definition ·resolved·
9179 * to by the ·actual value· of the type [attribute] ...
9180 */
9181 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9182 elem->namedTypeNs);
9183 if (type == NULL) {
9184 xmlSchemaPResCompAttrErr(ctxt,
9185 XML_SCHEMAP_SRC_RESOLVE,
9186 NULL, (xmlSchemaTypePtr) elem, elem->node,
9187 "type", elem->namedType, elem->namedTypeNs,
9188 XML_SCHEMA_TYPE_BASIC, "type definition");
9189 } else
9190 elem->subtypes = type;
9191 }
9192 if (elem->substGroup != NULL) {
9193 xmlSchemaElementPtr substHead;
9194
9195 /*
9196 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9197 * substitutionGroup?
9198 */
9199 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009200 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009201 if (substHead == NULL) {
9202 xmlSchemaPResCompAttrErr(ctxt,
9203 XML_SCHEMAP_SRC_RESOLVE,
9204 NULL, (xmlSchemaTypePtr) elem, NULL,
9205 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9206 XML_SCHEMA_TYPE_ELEMENT, NULL);
9207 } else {
9208 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9209 /*
9210 * (type definition)...otherwise the {type definition} of the
9211 * element declaration ·resolved· to by the ·actual value· of
9212 * the substitutionGroup [attribute], if present
9213 */
9214 if (elem->subtypes == NULL)
9215 elem->subtypes = substHead->subtypes;
9216 }
9217 }
9218 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9219 (elem->substGroup == NULL))
9220 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9221 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009222}
9223
William M. Bracke7091952004-05-11 15:09:58 +00009224/**
9225 * xmlSchemaParseListRefFixup:
9226 * @type: the schema type definition
9227 * @ctxt: the schema parser context
9228 *
9229 * Fixup of the itemType reference of the list type.
9230 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009231static void
William M. Bracke7091952004-05-11 15:09:58 +00009232xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009233{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009234
Daniel Veillard01fa6152004-06-29 17:04:39 +00009235 if (((type->base == NULL) &&
9236 (type->subtypes == NULL)) ||
9237 ((type->base != NULL) &&
9238 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009239 /*
9240 * src-list-itemType-or-simpleType
9241 * Either the itemType [attribute] or the <simpleType> [child] of
9242 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009243 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009244 /*
9245 * TODO: Move this to the parse function.
9246 */
9247 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009248 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009249 NULL, type, type->node,
9250 "The attribute 'itemType' and the <simpleType> child "
9251 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009252 } else if (type->base!= NULL) {
9253 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9254 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009255 xmlSchemaPResCompAttrErr(ctxt,
9256 XML_SCHEMAP_SRC_RESOLVE,
9257 NULL, type, type->node,
9258 "itemType", type->base, type->baseNs,
9259 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009260 }
9261 }
9262 if ((type->subtypes != NULL) &&
9263 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9264 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009265}
9266
9267/**
9268 * xmlSchemaParseUnionRefCheck:
9269 * @typeDecl: the schema type definition
9270 * @ctxt: the schema parser context
9271 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009272 * Checks and builds the memberTypes of the union type.
9273 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009274 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009275static int
William M. Bracke7091952004-05-11 15:09:58 +00009276xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009277 xmlSchemaParserCtxtPtr ctxt)
9278{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009279
Daniel Veillard01fa6152004-06-29 17:04:39 +00009280 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9281 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009282
Daniel Veillard01fa6152004-06-29 17:04:39 +00009283 /* 1 If the <union> alternative is chosen, then [Definition:]
9284 * define the explicit members as the type definitions ·resolved·
9285 * to by the items in the ·actual value· of the memberTypes [attribute],
9286 * if any, followed by the type definitions corresponding to the
9287 * <simpleType>s among the [children] of <union>, if any.
9288 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009289
Daniel Veillard01fa6152004-06-29 17:04:39 +00009290 if (type->type != XML_SCHEMA_TYPE_UNION)
9291 return (-1);
9292 if (ctxt->ctxtType == NULL) {
9293 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009294 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009295 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9296 "available", NULL, NULL);
9297 return (-1);
9298 }
9299 /*
9300 * src-union-memberTypes-or-simpleTypes
9301 * Either the memberTypes [attribute] of the <union> element must
9302 * be non-empty or there must be at least one simpleType [child].
9303 */
9304 if ((type->base == NULL) &&
9305 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009306 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009307 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009308 NULL, NULL, type->node,
9309 "Either the attribute 'memberTypes' must be non-empty "
9310 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009311 }
9312
9313 ctxtType = ctxt->ctxtType;
9314 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009315 xmlAttrPtr attr;
9316 const xmlChar *cur, *end;
9317 xmlChar *tmp;
9318 const xmlChar *localName, *uri;
9319
9320 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009321 cur = type->base;
9322 do {
9323 while (IS_BLANK_CH(*cur))
9324 cur++;
9325 end = cur;
9326 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9327 end++;
9328 if (end == cur)
9329 break;
9330 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009331 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9332 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9333 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009334 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009335 xmlSchemaPResCompAttrErr(ctxt,
9336 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9337 NULL, NULL, type->node, "memberTypes", localName, uri,
9338 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009339 } else {
9340 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9341 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9342 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9343 if (link == NULL) {
9344 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9345 return (-1);
9346 }
9347 link->type = memberType;
9348 link->next = NULL;
9349 if (lastLink == NULL)
9350 ctxtType->memberTypes = link;
9351 else
9352 lastLink->next = link;
9353 lastLink = link;
9354 }
9355 xmlFree(tmp);
9356 cur = end;
9357 } while (*cur != 0);
9358 }
9359 /*
9360 * Add local simple types,
9361 */
9362 memberType = type->subtypes;
9363 while (memberType != NULL) {
9364 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9365 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9366 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9367 if (link == NULL) {
9368 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9369 return (-1);
9370 }
9371 link->type = memberType;
9372 link->next = NULL;
9373 if (lastLink == NULL)
9374 ctxtType->memberTypes = link;
9375 else
9376 lastLink->next = link;
9377 lastLink = link;
9378 memberType = memberType->next;
9379 }
9380 /*
9381 * The actual value is then formed by replacing any union type
9382 * definition in the ·explicit members· with the members of their
9383 * {member type definitions}, in order.
9384 */
9385 link = ctxtType->memberTypes;
9386 while (link != NULL) {
9387 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9388 subLink = link->type->memberTypes;
9389 if (subLink != NULL) {
9390 link->type = subLink->type;
9391 if (subLink->next != NULL) {
9392 lastLink = link->next;
9393 subLink = subLink->next;
9394 prevLink = link;
9395 while (subLink != NULL) {
9396 newLink = (xmlSchemaTypeLinkPtr)
9397 xmlMalloc(sizeof(xmlSchemaTypeLink));
9398 if (newLink == NULL) {
9399 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9400 NULL);
9401 return (-1);
9402 }
9403 newLink->type = memberType;
9404 prevLink->next = newLink;
9405 prevLink = newLink;
9406 newLink->next = lastLink;
9407
9408 subLink = subLink->next;
9409 }
9410 }
9411 }
9412 }
9413 link = link->next;
9414 }
9415
9416 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009417}
9418
Daniel Veillard4255d502002-04-16 15:50:10 +00009419/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009420 * xmlSchemaIsDerivedFromBuiltInType:
9421 * @ctxt: the schema parser context
9422 * @type: the type definition
9423 * @valType: the value type
9424 *
9425 *
9426 * Returns 1 if the type has the given value type, or
9427 * is derived from such a type.
9428 */
William M. Brack803812b2004-06-03 02:11:24 +00009429static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009430xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9431 xmlSchemaTypePtr type, int valType)
9432{
9433 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009434 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009435 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009436 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009437 return(1);
9438 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9439 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9440 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9441 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9442 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9443 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9444 if (type->baseType != NULL)
9445 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9446 valType));
9447 } else if ((type->subtypes != NULL) &&
9448 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9449 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9450 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9451 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9452 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9453 valType));
9454 }
9455
9456 return (0);
9457}
9458
9459/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009460 * xmlSchemaIsDerivedFromBuiltInType:
9461 * @type: the simpleType definition
9462 *
9463 * Returns the primitive type of the given type or
9464 * NULL in case of error.
9465 */
9466static xmlSchemaTypePtr
9467xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9468{
9469 while (type != NULL) {
9470 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9471 return (type);
9472 type = type->baseType;
9473 }
9474
9475 return (NULL);
9476}
9477
9478
9479/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009480 * xmlSchemaBuildAttributeUsesOwned:
9481 * @ctxt: the schema parser context
9482 * @type: the complex type definition
9483 * @cur: the attribute declaration list
9484 * @lastUse: the top of the attribute use list
9485 *
9486 * Builds the attribute uses list on the given complex type.
9487 * This one is supposed to be called by
9488 * xmlSchemaBuildAttributeValidation only.
9489 */
9490static int
9491xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9492 xmlSchemaAttributePtr cur,
9493 xmlSchemaAttributeLinkPtr *uses,
9494 xmlSchemaAttributeLinkPtr *lastUse)
9495{
9496 xmlSchemaAttributeLinkPtr tmp;
9497 while (cur != NULL) {
9498 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9499 /*
9500 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9501 * to by the ·actual value·s of the ref [attribute] of the
9502 * <attributeGroup> [children], if any."
9503 */
9504 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9505 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9506 lastUse) == -1) {
9507 return (-1);
9508 }
9509 } else {
9510 /* W3C: "1 The set of attribute uses corresponding to the
9511 * <attribute> [children], if any."
9512 */
9513 tmp = (xmlSchemaAttributeLinkPtr)
9514 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9515 if (tmp == NULL) {
9516 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9517 return (-1);
9518 }
9519 tmp->attr = cur;
9520 tmp->next = NULL;
9521 if (*uses == NULL)
9522 *uses = tmp;
9523 else
9524 (*lastUse)->next = tmp;
9525 *lastUse = tmp;
9526 }
9527 cur = cur->next;
9528 }
9529 return (0);
9530}
9531
Daniel Veillard50355f02004-06-08 17:52:16 +00009532/**
9533 * xmlSchemaCloneWildcardNsConstraints:
9534 * @ctxt: the schema parser context
9535 * @dest: the destination wildcard
9536 * @source: the source wildcard
9537 *
9538 * Clones the namespace constraints of source
9539 * and assignes them to dest.
9540 * Returns -1 on internal error, 0 otherwise.
9541 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009542static int
9543xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9544 xmlSchemaWildcardPtr *dest,
9545 xmlSchemaWildcardPtr source)
9546{
9547 xmlSchemaWildcardNsPtr cur, tmp, last;
9548
9549 if ((source == NULL) || (*dest == NULL))
9550 return(-1);
9551 (*dest)->any = source->any;
9552 cur = source->nsSet;
9553 last = NULL;
9554 while (cur != NULL) {
9555 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9556 if (tmp == NULL)
9557 return(-1);
9558 tmp->value = cur->value;
9559 if (last == NULL)
9560 (*dest)->nsSet = tmp;
9561 else
9562 last->next = tmp;
9563 last = tmp;
9564 cur = cur->next;
9565 }
9566 if ((*dest)->negNsSet != NULL)
9567 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9568 if (source->negNsSet != NULL) {
9569 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9570 if ((*dest)->negNsSet == NULL)
9571 return(-1);
9572 (*dest)->negNsSet->value = source->negNsSet->value;
9573 } else
9574 (*dest)->negNsSet = NULL;
9575 return(0);
9576}
9577
Daniel Veillard50355f02004-06-08 17:52:16 +00009578/**
9579 * xmlSchemaUnionWildcards:
9580 * @ctxt: the schema parser context
9581 * @completeWild: the first wildcard
9582 * @curWild: the second wildcard
9583 *
9584 * Unions the namespace constraints of the given wildcards.
9585 * @completeWild will hold the resulting union.
9586 * Returns a positive error code on failure, -1 in case of an
9587 * internal error, 0 otherwise.
9588 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009589static int
9590xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9591 xmlSchemaWildcardPtr completeWild,
9592 xmlSchemaWildcardPtr curWild)
9593{
9594 xmlSchemaWildcardNsPtr cur, curB, tmp;
9595
9596 /*
9597 * 1 If O1 and O2 are the same value, then that value must be the
9598 * value.
9599 */
9600 if ((completeWild->any == curWild->any) &&
9601 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9602 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9603
9604 if ((completeWild->negNsSet == NULL) ||
9605 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9606
9607 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009608 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009609
9610 /*
9611 * Check equality of sets.
9612 */
9613 cur = completeWild->nsSet;
9614 while (cur != NULL) {
9615 found = 0;
9616 curB = curWild->nsSet;
9617 while (curB != NULL) {
9618 if (cur->value == curB->value) {
9619 found = 1;
9620 break;
9621 }
9622 curB = curB->next;
9623 }
9624 if (!found)
9625 break;
9626 cur = cur->next;
9627 }
9628 if (found)
9629 return(0);
9630 } else
9631 return(0);
9632 }
9633 }
9634 /*
9635 * 2 If either O1 or O2 is any, then any must be the value
9636 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009637 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009638 if (completeWild->any == 0) {
9639 completeWild->any = 1;
9640 if (completeWild->nsSet != NULL) {
9641 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9642 completeWild->nsSet = NULL;
9643 }
9644 if (completeWild->negNsSet != NULL) {
9645 xmlFree(completeWild->negNsSet);
9646 completeWild->negNsSet = NULL;
9647 }
9648 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009649 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009650 }
9651 /*
9652 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9653 * then the union of those sets must be the value.
9654 */
9655 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9656 int found;
9657 xmlSchemaWildcardNsPtr start;
9658
9659 cur = curWild->nsSet;
9660 start = completeWild->nsSet;
9661 while (cur != NULL) {
9662 found = 0;
9663 curB = start;
9664 while (curB != NULL) {
9665 if (cur->value == curB->value) {
9666 found = 1;
9667 break;
9668 }
9669 curB = curB->next;
9670 }
9671 if (!found) {
9672 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9673 if (tmp == NULL)
9674 return (-1);
9675 tmp->value = cur->value;
9676 tmp->next = completeWild->nsSet;
9677 completeWild->nsSet = tmp;
9678 }
9679 cur = cur->next;
9680 }
9681
9682 return(0);
9683 }
9684 /*
9685 * 4 If the two are negations of different values (namespace names
9686 * or ·absent·), then a pair of not and ·absent· must be the value.
9687 */
9688 if ((completeWild->negNsSet != NULL) &&
9689 (curWild->negNsSet != NULL) &&
9690 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9691 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009692
9693 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009694 }
9695 /*
9696 * 5.
9697 */
9698 if (((completeWild->negNsSet != NULL) &&
9699 (completeWild->negNsSet->value != NULL) &&
9700 (curWild->nsSet != NULL)) ||
9701 ((curWild->negNsSet != NULL) &&
9702 (curWild->negNsSet->value != NULL) &&
9703 (completeWild->nsSet != NULL))) {
9704
9705 int nsFound, absentFound = 0;
9706
9707 if (completeWild->nsSet != NULL) {
9708 cur = completeWild->nsSet;
9709 curB = curWild->negNsSet;
9710 } else {
9711 cur = curWild->nsSet;
9712 curB = completeWild->negNsSet;
9713 }
9714 nsFound = 0;
9715 while (cur != NULL) {
9716 if (cur->value == NULL)
9717 absentFound = 1;
9718 else if (cur->value == curB->value)
9719 nsFound = 1;
9720 if (nsFound && absentFound)
9721 break;
9722 cur = cur->next;
9723 }
9724
9725 if (nsFound && absentFound) {
9726 /*
9727 * 5.1 If the set S includes both the negated namespace
9728 * name and ·absent·, then any must be the value.
9729 */
9730 completeWild->any = 1;
9731 if (completeWild->nsSet != NULL) {
9732 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9733 completeWild->nsSet = NULL;
9734 }
9735 if (completeWild->negNsSet != NULL) {
9736 xmlFree(completeWild->negNsSet);
9737 completeWild->negNsSet = NULL;
9738 }
9739 } else if (nsFound && (!absentFound)) {
9740 /*
9741 * 5.2 If the set S includes the negated namespace name
9742 * but not ·absent·, then a pair of not and ·absent· must
9743 * be the value.
9744 */
9745 if (completeWild->nsSet != NULL) {
9746 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9747 completeWild->nsSet = NULL;
9748 }
9749 if (completeWild->negNsSet == NULL) {
9750 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9751 if (completeWild->negNsSet == NULL)
9752 return (-1);
9753 }
9754 completeWild->negNsSet->value = NULL;
9755 } else if ((!nsFound) && absentFound) {
9756 /*
9757 * 5.3 If the set S includes ·absent· but not the negated
9758 * namespace name, then the union is not expressible.
9759 */
9760 xmlSchemaPErr(ctxt, completeWild->node,
9761 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009762 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009763 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009764 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009765 } else if ((!nsFound) && (!absentFound)) {
9766 /*
9767 * 5.4 If the set S does not include either the negated namespace
9768 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9769 * and a namespace name must be the value.
9770 */
9771 if (completeWild->negNsSet == NULL) {
9772 if (completeWild->nsSet != NULL) {
9773 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9774 completeWild->nsSet = NULL;
9775 }
9776 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9777 if (completeWild->negNsSet == NULL)
9778 return (-1);
9779 completeWild->negNsSet->value = curWild->negNsSet->value;
9780 }
9781 }
9782 return (0);
9783 }
9784 /*
9785 * 6.
9786 */
9787 if (((completeWild->negNsSet != NULL) &&
9788 (completeWild->negNsSet->value == NULL) &&
9789 (curWild->nsSet != NULL)) ||
9790 ((curWild->negNsSet != NULL) &&
9791 (curWild->negNsSet->value == NULL) &&
9792 (completeWild->nsSet != NULL))) {
9793
9794 if (completeWild->nsSet != NULL) {
9795 cur = completeWild->nsSet;
9796 } else {
9797 cur = curWild->nsSet;
9798 }
9799 while (cur != NULL) {
9800 if (cur->value == NULL) {
9801 /*
9802 * 6.1 If the set S includes ·absent·, then any must be the
9803 * value.
9804 */
9805 completeWild->any = 1;
9806 if (completeWild->nsSet != NULL) {
9807 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9808 completeWild->nsSet = NULL;
9809 }
9810 if (completeWild->negNsSet != NULL) {
9811 xmlFree(completeWild->negNsSet);
9812 completeWild->negNsSet = NULL;
9813 }
9814 return (0);
9815 }
9816 cur = cur->next;
9817 }
9818 if (completeWild->negNsSet == NULL) {
9819 /*
9820 * 6.2 If the set S does not include ·absent·, then a pair of not
9821 * and ·absent· must be the value.
9822 */
9823 if (completeWild->nsSet != NULL) {
9824 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9825 completeWild->nsSet = NULL;
9826 }
9827 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9828 if (completeWild->negNsSet == NULL)
9829 return (-1);
9830 completeWild->negNsSet->value = NULL;
9831 }
9832 return (0);
9833 }
9834 return (0);
9835
9836}
9837
Daniel Veillard50355f02004-06-08 17:52:16 +00009838/**
9839 * xmlSchemaIntersectWildcards:
9840 * @ctxt: the schema parser context
9841 * @completeWild: the first wildcard
9842 * @curWild: the second wildcard
9843 *
9844 * Intersects the namespace constraints of the given wildcards.
9845 * @completeWild will hold the resulting intersection.
9846 * Returns a positive error code on failure, -1 in case of an
9847 * internal error, 0 otherwise.
9848 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009849static int
9850xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9851 xmlSchemaWildcardPtr completeWild,
9852 xmlSchemaWildcardPtr curWild)
9853{
William M. Brack803812b2004-06-03 02:11:24 +00009854 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009855
9856 /*
9857 * 1 If O1 and O2 are the same value, then that value must be the
9858 * value.
9859 */
9860 if ((completeWild->any == curWild->any) &&
9861 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9862 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9863
9864 if ((completeWild->negNsSet == NULL) ||
9865 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9866
9867 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009868 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009869
9870 /*
9871 * Check equality of sets.
9872 */
9873 cur = completeWild->nsSet;
9874 while (cur != NULL) {
9875 found = 0;
9876 curB = curWild->nsSet;
9877 while (curB != NULL) {
9878 if (cur->value == curB->value) {
9879 found = 1;
9880 break;
9881 }
9882 curB = curB->next;
9883 }
9884 if (!found)
9885 break;
9886 cur = cur->next;
9887 }
9888 if (found)
9889 return(0);
9890 } else
9891 return(0);
9892 }
9893 }
9894 /*
9895 * 2 If either O1 or O2 is any, then the other must be the value.
9896 */
9897 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9898 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9899 return(-1);
9900 return(0);
9901 }
9902 /*
9903 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9904 * name or ·absent·) and the other is a set of (namespace names or
9905 * ·absent·), then that set, minus the negated value if it was in
9906 * the set, minus ·absent· if it was in the set, must be the value.
9907 */
9908 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9909 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9910 const xmlChar *neg;
9911
9912 if (completeWild->nsSet == NULL) {
9913 neg = completeWild->negNsSet->value;
9914 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9915 return(-1);
9916 } else
9917 neg = curWild->negNsSet->value;
9918 /*
9919 * Remove absent and negated.
9920 */
9921 prev = NULL;
9922 cur = completeWild->nsSet;
9923 while (cur != NULL) {
9924 if (cur->value == NULL) {
9925 if (prev == NULL)
9926 completeWild->nsSet = cur->next;
9927 else
9928 prev->next = cur->next;
9929 xmlFree(cur);
9930 break;
9931 }
9932 prev = cur;
9933 cur = cur->next;
9934 }
9935 if (neg != NULL) {
9936 prev = NULL;
9937 cur = completeWild->nsSet;
9938 while (cur != NULL) {
9939 if (cur->value == neg) {
9940 if (prev == NULL)
9941 completeWild->nsSet = cur->next;
9942 else
9943 prev->next = cur->next;
9944 xmlFree(cur);
9945 break;
9946 }
9947 prev = cur;
9948 cur = cur->next;
9949 }
9950 }
9951
9952 return(0);
9953 }
9954 /*
9955 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9956 * then the intersection of those sets must be the value.
9957 */
9958 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9959 int found;
9960
9961 cur = completeWild->nsSet;
9962 prev = NULL;
9963 while (cur != NULL) {
9964 found = 0;
9965 curB = curWild->nsSet;
9966 while (curB != NULL) {
9967 if (cur->value == curB->value) {
9968 found = 1;
9969 break;
9970 }
9971 curB = curB->next;
9972 }
9973 if (!found) {
9974 if (prev == NULL)
9975 completeWild->nsSet = cur->next;
9976 else
9977 prev->next = cur->next;
9978 tmp = cur->next;
9979 xmlFree(cur);
9980 cur = tmp;
9981 continue;
9982 }
9983 prev = cur;
9984 cur = cur->next;
9985 }
9986
9987 return(0);
9988 }
9989 /* 5 If the two are negations of different namespace names,
9990 * then the intersection is not expressible
9991 */
9992 if ((completeWild->negNsSet != NULL) &&
9993 (curWild->negNsSet != NULL) &&
9994 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9995 (completeWild->negNsSet->value != NULL) &&
9996 (curWild->negNsSet->value != NULL)) {
9997
9998 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009999 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010000 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010001 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010002 }
10003 /*
10004 * 6 If the one is a negation of a namespace name and the other
10005 * is a negation of ·absent·, then the one which is the negation
10006 * of a namespace name must be the value.
10007 */
10008 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10009 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10010 (completeWild->negNsSet->value == NULL)) {
10011 completeWild->negNsSet->value = curWild->negNsSet->value;
10012 }
10013 return(0);
10014}
10015
Daniel Veillard50355f02004-06-08 17:52:16 +000010016/**
10017 * xmlSchemaIsWildcardNsConstraintSubset:
10018 * @ctxt: the schema parser context
10019 * @wildA: the first wildcard
10020 * @wildB: the second wildcard
10021 *
10022 * Returns 1 if the namespace constraint of @wildA is an intensional
10023 * subset of @wildB, 0 otherwise.
10024 */
10025static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010026xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10027 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010028{
Daniel Veillard3646d642004-06-02 19:19:14 +000010029
Daniel Veillard50355f02004-06-08 17:52:16 +000010030 /*
10031 * Schema Component Constraint: Wildcard Subset
10032 */
10033 /*
10034 * 1 super must be any.
10035 */
10036 if (wildB->any)
10037 return (1);
10038 /*
10039 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10040 * 2.2 super must be a pair of not and the same value.
10041 */
10042 if ((wildA->negNsSet != NULL) &&
10043 (wildB->negNsSet != NULL) &&
10044 (wildA->negNsSet->value == wildA->negNsSet->value))
10045 return (1);
10046 /*
10047 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10048 */
10049 if (wildA->nsSet != NULL) {
10050 /*
10051 * 3.2.1 super must be the same set or a superset thereof.
10052 */
10053 if (wildB->nsSet != NULL) {
10054 xmlSchemaWildcardNsPtr cur, curB;
10055 int found = 0;
10056
10057 cur = wildA->nsSet;
10058 while (cur != NULL) {
10059 found = 0;
10060 curB = wildB->nsSet;
10061 while (curB != NULL) {
10062 if (cur->value == curB->value) {
10063 found = 1;
10064 break;
10065 }
10066 curB = curB->next;
10067 }
10068 if (!found)
10069 return (0);
10070 cur = cur->next;
10071 }
10072 if (found)
10073 return (1);
10074 } else if (wildB->negNsSet != NULL) {
10075 xmlSchemaWildcardNsPtr cur;
10076 /*
10077 * 3.2.2 super must be a pair of not and a namespace name or
10078 * ·absent· and that value must not be in sub's set.
10079 */
10080 cur = wildA->nsSet;
10081 while (cur != NULL) {
10082 if (cur->value == wildB->negNsSet->value)
10083 return (0);
10084 cur = cur->next;
10085 }
10086 return (1);
10087 }
10088 }
10089 return (0);
10090}
10091
10092/**
10093 * xmlSchemaBuildCompleteAttributeWildcard:
10094 * @ctxt: the schema parser context
10095 * @attrs: the attribute list
10096 * @completeWild: the resulting complete wildcard
10097 *
10098 * Returns -1 in case of an internal error, 0 otherwise.
10099 */
10100static int
10101xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10102 xmlSchemaAttributePtr attrs,
10103 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010104{
10105 while (attrs != NULL) {
10106 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10107 xmlSchemaAttributeGroupPtr group;
10108
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010109 group = (xmlSchemaAttributeGroupPtr) attrs;
10110 /*
10111 * Handle attribute group references.
10112 */
10113 if (group->ref != NULL) {
10114 if (group->refItem == NULL) {
10115 /*
10116 * TODO: Should we raise a warning here?
10117 */
10118 /*
10119 * The referenced attribute group definition could not
10120 * be resolved beforehand, so skip.
10121 */
10122 attrs = attrs->next;
10123 continue;
10124 } else
10125 group = group->refItem;
10126 }
10127 /*
10128 * For every attribute group definition, an intersected wildcard
10129 * will be created (assumed that a wildcard exists on the
10130 * particular attr. gr. def. or on any contained attr. gr. def
10131 * at all).
10132 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10133 * that the intersection will be performed only once.
10134 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010135 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10136 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010137 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10138 group->attributes, &group->attributeWildcard) == -1)
10139 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010140 }
10141 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10142 }
10143 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010144 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010145 /*
10146 * Copy the first encountered wildcard as context, except for the annotation.
10147 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010148 *completeWild = xmlSchemaAddWildcard(ctxt);
10149 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10150 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10151 completeWild, group->attributeWildcard) == -1)
10152 return (-1);
10153 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010154 /*
10155 * Although the complete wildcard might not correspond to any
10156 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010157 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010158 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010159 (*completeWild)->node = group->attributeWildcard->node;
10160
10161 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10162 xmlSchemaFreeWildcard(*completeWild);
10163 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010164 }
10165 }
10166 }
10167 attrs = attrs->next;
10168 }
10169
Daniel Veillard50355f02004-06-08 17:52:16 +000010170 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010171}
10172
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010173static int
10174xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10175 int *fixed,
10176 const xmlChar **value,
10177 xmlSchemaValPtr *val)
10178{
10179 *fixed = 0;
10180 *value = NULL;
10181 if (val != 0)
10182 *val = NULL;
10183
10184 if (item->defValue == NULL)
10185 item = item->refDecl;
10186
10187 if (item == NULL)
10188 return (0);
10189
10190 if (item->defValue != NULL) {
10191 *value = item->defValue;
10192 if (val != 0)
10193 *val = item->defVal;
10194 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10195 *fixed = 1;
10196 return (1);
10197 }
10198 return (0);
10199}
Daniel Veillard3646d642004-06-02 19:19:14 +000010200/**
10201 * xmlSchemaMatchesWildcardNs:
10202 * @wild: the wildcard
10203 * @ns: the namespace
10204 *
10205 *
10206 * Returns 1 if the given namespace matches the wildcard,
10207 * 0 otherwise.
10208 */
10209static int
10210xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10211{
10212 if (wild == NULL)
10213 return(0);
10214
10215 if (wild->any)
10216 return(1);
10217 else if (wild->nsSet != NULL) {
10218 xmlSchemaWildcardNsPtr cur;
10219
10220 cur = wild->nsSet;
10221 while (cur != NULL) {
10222 if (xmlStrEqual(cur->value, ns))
10223 return(1);
10224 cur = cur->next;
10225 }
10226 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10227 (!xmlStrEqual(wild->negNsSet->value, ns)))
10228 return(1);
10229
10230 return(0);
10231}
10232
10233/**
10234 * xmlSchemaBuildAttributeValidation:
10235 * @ctxt: the schema parser context
10236 * @type: the complex type definition
10237 *
10238 *
10239 * Builds the wildcard and the attribute uses on the given complex type.
10240 * Returns -1 if an internal error occurs, 0 otherwise.
10241 */
10242static int
10243xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10244{
10245 xmlSchemaTypePtr baseType = NULL;
10246 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010247 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010248 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010249 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010250 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010251 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010252 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010253
Daniel Veillard01fa6152004-06-29 17:04:39 +000010254 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010255 /*
10256 * Complex Type Definition with complex content Schema Component.
10257 *
10258 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010259 * TODO: Add checks for absent referenced attribute declarations and
10260 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010261 */
10262 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010263 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010264 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010265 "attribute uses already builded.\n",
10266 NULL, NULL);
10267 return (-1);
10268 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010269 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010270 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010271 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010272 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010273 type->name, NULL);
10274 return (-1);
10275 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010276 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010277 if (baseType == anyType)
10278 baseIsAnyType = 1;
10279 /*
10280 * Inherit the attribute uses of the base type.
10281 */
10282 /*
10283 * NOTE: It is allowed to "extend" the anyType complex type.
10284 */
10285 if (!baseIsAnyType) {
10286 if (baseType != NULL) {
10287 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10288 tmp = (xmlSchemaAttributeLinkPtr)
10289 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10290 if (tmp == NULL) {
10291 xmlSchemaPErrMemory(ctxt,
10292 "building attribute uses of complexType", NULL);
10293 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010294 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010295 tmp->attr = cur->attr;
10296 tmp->next = NULL;
10297 if (type->attributeUses == NULL) {
10298 type->attributeUses = tmp;
10299 } else
10300 lastBaseUse->next = tmp;
10301 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010302 }
10303 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010304 }
10305 if ((type->subtypes != NULL) &&
10306 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10307 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010308 /*
10309 * type --> (<simpleContent>|<complexContent>)
10310 * --> (<restriction>|<extension>) --> attributes
10311 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010312 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010313 } else {
10314 /* Short hand form of the complexType. */
10315 attrs = type->attributes;
10316 }
10317 /*
10318 * Handle attribute wildcards.
10319 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010320 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10321 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010322 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010323 * NOTE: During the parse time, the wildcard is created on the complexType
10324 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010325 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010326 if (err == -1) {
10327 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10328 "Internal error: xmlSchemaBuildAttributeValidation: "
10329 "failed to build an intersected attribute wildcard.\n",
10330 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010331 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010332 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010333
10334 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10335 ((baseIsAnyType) ||
10336 ((baseType != NULL) &&
10337 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10338 (baseType->attributeWildcard != NULL)))) {
10339 if (type->attributeWildcard != NULL) {
10340 /*
10341 * Union the complete wildcard with the base wildcard.
10342 */
10343 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10344 baseType->attributeWildcard) == -1)
10345 return (-1);
10346 } else {
10347 /*
10348 * Just inherit the wildcard.
10349 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010350 /*
10351 * NOTE: This is the only case where an attribute
10352 * wildcard is shared.
10353 */
10354 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10355 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010356 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010357 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010358 }
10359
10360 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10361 if (type->attributeWildcard != NULL) {
10362 /*
10363 * Derivation Valid (Restriction, Complex)
10364 * 4.1 The {base type definition} must also have one.
10365 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010366 if (baseType->attributeWildcard == NULL) {
10367 xmlSchemaPCustomErr(ctxt,
10368 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10369 NULL, type, NULL,
10370 "The type has an attribute wildcard, "
10371 "but the base type %s does not have one",
10372 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10373 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010374 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010375 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010376 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10377 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010378 xmlSchemaPCustomErr(ctxt,
10379 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10380 NULL, type, NULL,
10381 "The attribute wildcard is not a valid "
10382 "subset of the wildcard in the base type %s",
10383 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10384 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010385 return (1);
10386 }
10387 /* 4.3 Unless the {base type definition} is the ·ur-type
10388 * definition·, the complex type definition's {attribute
10389 * wildcard}'s {process contents} must be identical to or
10390 * stronger than the {base type definition}'s {attribute
10391 * wildcard}'s {process contents}, where strict is stronger
10392 * than lax is stronger than skip.
10393 */
10394 if ((type->baseType != anyType) &&
10395 (type->attributeWildcard->processContents <
10396 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010397 xmlSchemaPCustomErr(ctxt,
10398 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10399 NULL, type, NULL,
10400 "The 'process contents' of the attribute wildcard is weaker than "
10401 "the one in the base type %s",
10402 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10403 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010404 return (1);
10405 }
10406 }
10407 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10408 /*
10409 * Derivation Valid (Extension)
10410 * At this point the type and the base have both, either
10411 * no wildcard or a wildcard.
10412 */
10413 if ((baseType->attributeWildcard != NULL) &&
10414 (baseType->attributeWildcard != type->attributeWildcard)) {
10415 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010416 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010417 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010418 xmlSchemaPCustomErr(ctxt,
10419 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10420 NULL, type, NULL,
10421 "The attribute wildcard is not a valid "
10422 "superset of the one in the base type %s",
10423 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10424 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010425 return (1);
10426 }
10427 }
10428 }
10429
Daniel Veillard3646d642004-06-02 19:19:14 +000010430 /*
10431 * Gather attribute uses defined by this type.
10432 */
10433 if (attrs != NULL) {
10434 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10435 &uses, &lastUse) == -1) {
10436 return (-1);
10437 }
10438 }
10439 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10440 * "Two distinct attribute declarations in the {attribute uses} must
10441 * not have identical {name}s and {target namespace}s."
10442 *
10443 * For "extension" this is done further down.
10444 */
10445 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10446 cur = uses;
10447 while (cur != NULL) {
10448 tmp = cur->next;
10449 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010450 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10451 xmlSchemaGetAttrName(tmp->attr))) &&
10452 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10453 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10454
10455 xmlSchemaPAttrUseErr(ctxt,
10456 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10457 NULL, type, NULL, cur->attr,
10458 "Duplicate attribute use %s specified",
10459 xmlSchemaFormatNsUriLocal(&str,
10460 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10461 xmlSchemaGetAttrName(tmp->attr))
10462 );
10463 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010464 break;
10465 }
10466 tmp = tmp->next;
10467 }
10468 cur = cur->next;
10469 }
10470 }
10471 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10472 /*
10473 * Derive by restriction.
10474 */
10475 if (baseIsAnyType) {
10476 type->attributeUses = uses;
10477 } else {
10478 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010479 const xmlChar *bEffValue;
10480 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010481
10482 cur = uses;
10483 while (cur != NULL) {
10484 found = 0;
10485 base = type->attributeUses;
10486 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010487 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10488 xmlSchemaGetAttrName(base->attr)) &&
10489 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10490 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010491
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010492 found = 1;
10493
Daniel Veillard3646d642004-06-02 19:19:14 +000010494 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10495 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10496 /*
10497 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010498 */
10499 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010500 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010501 NULL, type, NULL, cur->attr,
10502 "The 'optional' use is inconsistent with a matching "
10503 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010504 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10505 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10506 /*
10507 * derivation-ok-restriction 3
10508 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010509 xmlSchemaPCustomErr(ctxt,
10510 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10511 NULL, type, NULL,
10512 "A matching attribute use for the 'required' "
10513 "attribute use %s of the base type is missing",
10514 xmlSchemaFormatNsUriLocal(&str,
10515 xmlSchemaGetAttrTargetNsURI(base->attr),
10516 xmlSchemaGetAttrName(base->attr)));
10517 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010518 } else {
10519 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010520 * 2.1.3 [Definition:] Let the effective value
10521 * constraint of an attribute use be its {value
10522 * constraint}, if present, otherwise its {attribute
10523 * declaration}'s {value constraint} .
10524 */
10525 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10526 &bEffValue, 0);
10527 /*
10528 * 2.1.3 ... one of the following must be true
10529 *
10530 * 2.1.3.1 B's ·effective value constraint· is
10531 * ·absent· or default.
10532 */
10533 if ((bEffValue != NULL) &&
10534 (effFixed == 1)) {
10535 const xmlChar *rEffValue = NULL;
10536
10537 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10538 &rEffValue, 0);
10539 /*
10540 * 2.1.3.2 R's ·effective value constraint· is
10541 * fixed with the same string as B's.
10542 */
10543 if ((effFixed == 0) ||
10544 (! xmlStrEqual(rEffValue, bEffValue))) {
10545 xmlSchemaPAttrUseErr(ctxt,
10546 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10547 NULL, type, NULL, cur->attr,
10548 "The effective value constraint of the "
10549 "attribute use is inconsistent with "
10550 "its correspondent of the base type",
10551 NULL);
10552 }
10553 }
10554 /*
10555 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10556 */
10557 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010558 * Override the attribute use.
10559 */
10560 base->attr = cur->attr;
10561 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010562
Daniel Veillard3646d642004-06-02 19:19:14 +000010563 break;
10564 }
10565 base = base->next;
10566 }
10567
10568 if (!found) {
10569 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10570 /*
10571 * derivation-ok-restriction 2.2
10572 */
10573 if ((type->attributeWildcard != NULL) &&
10574 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10575 cur->attr->targetNamespace))
10576 found = 1;
10577
10578 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010579 xmlSchemaPAttrUseErr(ctxt,
10580 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10581 NULL, type, NULL, cur->attr,
10582 "Neither a matching attribute use, "
10583 "nor a matching wildcard in the base type does exist",
10584 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010585 } else {
10586 /*
10587 * Add the attribute use.
10588 *
10589 * Note that this may lead to funny derivation error reports, if
10590 * multiple equal attribute uses exist; but this is not
10591 * allowed anyway, and it will be reported beforehand.
10592 */
10593 tmp = cur;
10594 if (prev != NULL)
10595 prev->next = cur->next;
10596 else
10597 uses = cur->next;
10598 cur = cur->next;
10599 if (type->attributeUses == NULL) {
10600 type->attributeUses = tmp;
10601 } else
10602 lastBaseUse->next = tmp;
10603 lastBaseUse = tmp;
10604
10605 continue;
10606 }
10607 }
10608 }
10609 prev = cur;
10610 cur = cur->next;
10611 }
10612 if (uses != NULL)
10613 xmlSchemaFreeAttributeUseList(uses);
10614 }
10615 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10616 /*
10617 * The spec allows only appending, and not other kinds of extensions.
10618 *
10619 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10620 */
10621 if (uses != NULL) {
10622 if (type->attributeUses == NULL) {
10623 type->attributeUses = uses;
10624 } else
10625 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010626 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010627 } else {
10628 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010629 * Derive implicitely from the ur-type.
10630 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010631 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010632 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010633 /*
10634 * 3.4.6 -> Complex Type Definition Properties Correct
10635 */
10636 if (type->attributeUses != NULL) {
10637 cur = type->attributeUses;
10638 prev = NULL;
10639 while (cur != NULL) {
10640 /*
10641 * 4. Two distinct attribute declarations in the {attribute uses} must
10642 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010643 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010644 * Note that this was already done for "restriction" and types derived from
10645 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010646 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010647 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10648 tmp = cur->next;
10649 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010650 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10651 xmlSchemaGetAttrName(tmp->attr))) &&
10652 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10653 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010654
Daniel Veillardc0826a72004-08-10 14:17:33 +000010655 xmlSchemaPAttrUseErr(ctxt,
10656 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10657 NULL, type, NULL, tmp->attr,
10658 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010659 break;
10660 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010661 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010662 }
10663 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010664 /*
10665 * 5. Two distinct attribute declarations in the {attribute uses} must
10666 * not have {type definition}s which are or are derived from ID.
10667 */
10668 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010669 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010670 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010671 xmlSchemaPAttrUseErr(ctxt,
10672 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10673 NULL, type, NULL, cur->attr,
10674 "There must not exist more than one attribute use, "
10675 "declared of type 'ID' or derived from it",
10676 NULL);
10677 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010678 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010679 id = cur;
10680 }
10681 /*
10682 * Remove "prohibited" attribute uses. The reason this is done at this late
10683 * stage is to be able to catch dublicate attribute uses. So we had to keep
10684 * prohibited uses in the list as well.
10685 */
10686 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10687 tmp = cur;
10688 if (prev == NULL)
10689 type->attributeUses = cur->next;
10690 else
10691 prev->next = cur->next;
10692 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010693 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010694 } else {
10695 prev = cur;
10696 cur = cur->next;
10697 }
10698 }
10699 }
10700 /*
10701 * TODO: This check should be removed if we are 100% sure of
10702 * the base type attribute uses already being built.
10703 */
10704 if ((baseType != NULL) && (!baseIsAnyType) &&
10705 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10706 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010707 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010708 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010709 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010710 baseType->name, NULL);
10711 }
10712 return (0);
10713}
10714
10715/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010716 * xmlSchemaTypeFinalContains:
10717 * @schema: the schema
10718 * @type: the type definition
10719 * @final: the final
10720 *
10721 * Evaluates if a type definition contains the given "final".
10722 * This does take "finalDefault" into account as well.
10723 *
10724 * Returns 1 if the type does containt the given "final",
10725 * 0 otherwise.
10726 */
10727static int
10728xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10729{
10730 int tfinal = final, tflags = type->flags;
10731
10732 if (type == NULL)
10733 return (0);
10734 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10735 switch (final) {
10736 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10737 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10738 break;
10739 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10740 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10741 break;
10742 case XML_SCHEMAS_TYPE_FINAL_LIST:
10743 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10744 break;
10745 case XML_SCHEMAS_TYPE_FINAL_UNION:
10746 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10747 break;
10748 }
10749 tflags = schema->flags;
10750 }
10751 if (tflags & tfinal)
10752 return (1);
10753 else
10754 return (0);
10755
10756}
10757
10758/**
10759 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10760 * @type: the Union Simple Type
10761 *
10762 * Returns a list of member types of @type if existing,
10763 * returns NULL otherwise.
10764 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010765static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010766xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10767{
10768 while (type != NULL) {
10769 if (type->memberTypes != NULL)
10770 return (type->memberTypes);
10771 else
10772 type = type->baseType;
10773 }
10774 return (NULL);
10775}
10776
10777/**
10778 * xmlSchemaGetListSimpleTypeItemType:
10779 * @type: the simple type definition
10780 *
10781 * Returns the item type definition of the list simple type.
10782 */
10783static xmlSchemaTypePtr
10784xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10785{
10786 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10787 return (NULL);
10788 /*
10789 * Note: In libxml2, the built-in types do not reflect
10790 * the datatype hierarchy (yet?) - we have to treat them
10791 * in a special way.
10792 */
10793 if (type->type == XML_SCHEMA_TYPE_BASIC)
10794 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10795 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10796 /* 1 If the <list> alternative is chosen, then the type
10797 * definition ·resolved· to by the ·actual value· of the
10798 * itemType [attribute] of <list>, if present, otherwise
10799 * the type definition corresponding to the <simpleType>
10800 * among the [children] of <list>.
10801 */
10802 return (type->subtypes->subtypes);
10803 else {
10804 /* 2 If the <restriction> option is chosen, then the
10805 * {item type definition} of the {base type definition}.
10806 */
10807 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10808 }
10809}
10810
10811/**
10812 * xmlSchemaCheckCOSSTDerivedOK:
10813 * @type: the derived simple type definition
10814 * @baseType: the base type definition
10815 *
10816 * Checks wheter @type can be validly
10817 * derived from @baseType.
10818 *
10819 * Returns 0 on success, an positive error code otherwise.
10820 */
10821static int
10822xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10823 xmlSchemaTypePtr type,
10824 xmlSchemaTypePtr baseType,
10825 int subset)
10826{
10827 /*
10828 * Schema Component Constraint: Type Derivation OK (Simple)
10829 *
10830 *
10831 * 1 They are the same type definition.
10832 * TODO: The identy check might have to be more complex than this.
10833 */
10834 if (type == baseType)
10835 return (0);
10836 /*
10837 * 2.1 restriction is not in the subset, or in the {final}
10838 * of its own {base type definition};
10839 */
10840 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10841 (xmlSchemaTypeFinalContains(schema,
10842 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10843 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10844 }
10845 /* 2.2 */
10846 if (type->baseType == baseType) {
10847 /*
10848 * 2.2.1 D's ·base type definition· is B.
10849 */
10850 return (0);
10851 }
10852 /*
10853 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10854 * and is validly derived from B given the subset, as defined by this
10855 * constraint.
10856 */
10857 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10858 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10859 return (0);
10860 }
10861 /*
10862 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10863 * definition·.
10864 */
10865 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10866 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10867 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10868 return (0);
10869 }
10870 /*
10871 * 2.2.4 B's {variety} is union and D is validly derived from a type
10872 * definition in B's {member type definitions} given the subset, as
10873 * defined by this constraint.
10874 *
10875 * NOTE: This seems not to involve built-in types, since there is no
10876 * built-in Union Simple Type.
10877 */
10878 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10879 xmlSchemaTypeLinkPtr cur;
10880
10881 cur = baseType->memberTypes;
10882 while (cur != NULL) {
10883 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10884 cur->type, subset) == 0)
10885 return (0);
10886 cur = cur->next;
10887 }
10888 }
10889
10890 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10891}
10892
10893
10894/**
10895 * xmlSchemaCheckSTPropsCorrect:
10896 * @ctxt: the schema parser context
10897 * @type: the simple type definition
10898 *
10899 * Checks st-props-correct.
10900 *
10901 * Returns 0 if the properties are correct,
10902 * if not, a positive error code and -1 on internal
10903 * errors.
10904 */
10905static int
10906xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10907 xmlSchemaTypePtr type)
10908{
10909 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10910 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010911 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010912
Daniel Veillardc0826a72004-08-10 14:17:33 +000010913 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010914 /*
10915 * Schema Component Constraint: Simple Type Definition Properties Correct
10916 *
10917 * NOTE: This is somehow redundant, since we actually built a simple type
10918 * to have all the needed information; this acts as an self test.
10919 */
10920 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10921 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10922 /*
10923 * TODO: 1 The values of the properties of a simple type definition must be as
10924 * described in the property tableau in Datatype definition, modulo the
10925 * impact of Missing Sub-components (§5.3).
10926 */
10927 /* Base type: If the datatype has been ·derived· by ·restriction·
10928 * then the Simple Type Definition component from which it is ·derived·,
10929 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10930 */
10931 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010932 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010933 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010934 NULL, type, NULL,
10935 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010936 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10937 }
10938 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10939 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10940 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010941 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010942 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010943 NULL, type, NULL,
10944 "The base type %s is not a simple type",
10945 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10946 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010947 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10948 }
10949 if ((baseType != anySimpleType) &&
10950 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010951 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010952 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010953 NULL, type, NULL,
10954 "A type, derived by list or union, must have"
10955 "the simple ur-type definition as base type, not %s",
10956 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10957 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010958 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10959 }
10960 /*
10961 * Variety: One of {atomic, list, union}.
10962 */
10963 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10964 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10965 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010966 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010967 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010968 NULL, type, NULL,
10969 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010970 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10971 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010972 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010973
10974 /*
10975 * 2 All simple type definitions must be derived ultimately from the ·simple
10976 * ur-type definition (so· circular definitions are disallowed). That is, it
10977 * must be possible to reach a built-in primitive datatype or the ·simple
10978 * ur-type definition· by repeatedly following the {base type definition}.
10979 */
10980 baseType = type->baseType;
10981 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10982 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10983 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10984 if (baseType == anySimpleType)
10985 break;
10986 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010987 xmlSchemaPCustomErr(ctxt,
10988 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10989 NULL, type, NULL,
10990 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010991 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10992 }
10993 baseType = baseType->baseType;
10994 }
10995 /*
10996 * 3 The {final} of the {base type definition} must not contain restriction.
10997 */
10998 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10999 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011000 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011001 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011002 NULL, type, NULL,
11003 "The 'final' of its base type %s must not contain "
11004 "'restriction'",
11005 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11006 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011007 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11008 }
11009 return (0);
11010}
11011
11012/**
11013 * xmlSchemaCheckDerivationValidSimpleRestriction:
11014 * @ctxt: the schema parser context
11015 * @type: the simple type definition
11016 *
11017 * Checks if the given @type (simpleType) is derived
11018 * validly by restriction.
11019 *
11020 * Returns -1 on internal errors, 0 if the type is validly derived,
11021 * a positive error code otherwise.
11022 */
11023static int
11024xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011025 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011026{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011027 xmlChar *str = NULL;
11028
11029 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011030
11031 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11032 xmlSchemaPErr(ctxt, type->node,
11033 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011034 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11035 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011036 type->name, NULL);
11037 return (-1);
11038 }
11039
11040 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11041 xmlSchemaTypePtr primitive;
11042 /*
11043 * 1.1 The {base type definition} must be an atomic simple
11044 * type definition or a built-in primitive datatype.
11045 */
11046 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011047 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011048 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011049 NULL, type, NULL,
11050 "The base type %s is not an atomic simple type",
11051 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11052 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011053 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11054 }
11055 /* 1.2 The {final} of the {base type definition} must not contain
11056 * restriction.
11057 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011058 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011059 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11060 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011062 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011063 NULL, type, NULL,
11064 "The final of its base type %s must not contain 'restriction'",
11065 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11066 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011067 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11068 }
11069
11070 /*
11071 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11072 * type definition}, as specified in the appropriate subsection of 3.2
11073 * Primitive datatypes.
11074 */
11075 if (type->facets != NULL) {
11076 xmlSchemaFacetPtr facet;
11077 int ok = 1;
11078
11079 primitive = xmlSchemaGetPrimitiveType(type);
11080 if (primitive == NULL) {
11081 xmlSchemaPErr(ctxt, type->node,
11082 XML_ERR_INTERNAL_ERROR,
11083 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011084 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011085 type->name, NULL);
11086 return (-1);
11087 }
11088 facet = type->facets;
11089 do {
11090 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011091 ok = 0;
11092 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011093 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011094 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011095 }
11096 facet = facet->next;
11097 } while (facet != NULL);
11098 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011099 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011100 }
11101 /*
11102 * TODO: 1.3.2 (facet derivation)
11103 */
11104 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11105 xmlSchemaTypePtr itemType = NULL;
11106
11107 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11108 if (itemType == NULL) {
11109 xmlSchemaPErr(ctxt, type->node,
11110 XML_ERR_INTERNAL_ERROR,
11111 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011112 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011113 type->name, NULL);
11114 return (-1);
11115 }
11116 /*
11117 * 2.1 The {item type definition} must have a {variety} of atomic or
11118 * union (in which case all the {member type definitions}
11119 * must be atomic).
11120 */
11121 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11122 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011123 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011124 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011125 NULL, type, NULL,
11126 "The item type %s must have a variety of atomic or union",
11127 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11128 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011129 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11130 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11131 xmlSchemaTypeLinkPtr member;
11132
11133 member = itemType->memberTypes;
11134 while (member != NULL) {
11135 if ((member->type->flags &
11136 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011137 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011138 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 NULL, type, NULL,
11140 "The item type is a union type, but the "
11141 "member type %s of this item type is not atomic",
11142 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11143 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011144 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11145 }
11146 member = member->next;
11147 }
11148 }
11149
11150 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11151 xmlSchemaFacetPtr facet;
11152 /*
11153 * This is the case if we have: <simpleType><list ..
11154 */
11155 /*
11156 * 2.3.1
11157 * 2.3.1.1 The {final} of the {item type definition} must not
11158 * contain list.
11159 */
11160 if (xmlSchemaTypeFinalContains(ctxt->schema,
11161 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011162 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011163 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011164 NULL, type, NULL,
11165 "The final of its item type %s must not contain 'list'",
11166 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11167 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011168 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11169 }
11170 /*
11171 * 2.3.1.2 The {facets} must only contain the whiteSpace
11172 * facet component.
11173 */
11174 if (type->facets != NULL) {
11175 facet = type->facets;
11176 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011177 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11178 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011179 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011180 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011181 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11182 }
11183 facet = facet->next;
11184 } while (facet != NULL);
11185 }
11186 /*
11187 * TODO: Datatypes states:
11188 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11189 * whose ·lexical space· allows space (such as string or anyURI)or
11190 * a ·union· datatype any of whose {member type definitions}'s
11191 * ·lexical space· allows space.
11192 */
11193 } else {
11194 /*
11195 * This is the case if we have: <simpleType><restriction ...
11196 */
11197 /*
11198 * 2.3.2
11199 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11200 */
11201 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011202 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011203 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011204 NULL, type, NULL,
11205 "The base type %s must be a list type",
11206 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11207 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011208 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11209 }
11210 /*
11211 * 2.3.2.2 The {final} of the {base type definition} must not
11212 * contain restriction.
11213 */
11214 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11215 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011216 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011217 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011218 NULL, type, NULL,
11219 "The final of the base type %s must not contain 'restriction'",
11220 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11221 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011222 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11223 }
11224 /*
11225 * 2.3.2.3 The {item type definition} must be validly derived
11226 * from the {base type definition}'s {item type definition} given
11227 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11228 */
11229 {
11230 xmlSchemaTypePtr baseItemType;
11231
11232 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11233 if (baseItemType == NULL) {
11234 xmlSchemaPErr(ctxt, type->node,
11235 XML_ERR_INTERNAL_ERROR,
11236 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011237 "List simple type '%s': Failed to "
11238 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011239 type->name, type->baseType->name);
11240 return (-1);
11241 }
11242 if ((itemType != baseItemType) &&
11243 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11244 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011245 xmlChar *strBIT = NULL, *strBT = NULL;
11246 xmlSchemaPCustomErrExt(ctxt,
11247 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11248 NULL, type, NULL,
11249 "The item type %s is not validly derived from the "
11250 "item type %s of the base type %s",
11251 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11252 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11253 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11254
11255 FREE_AND_NULL(str)
11256 FREE_AND_NULL(strBIT)
11257 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011258 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11259 }
11260 }
11261
11262 if (type->facets != NULL) {
11263 xmlSchemaFacetPtr facet;
11264 int ok = 1;
11265 /*
11266 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11267 * and enumeration facet components are allowed among the {facets}.
11268 */
11269 facet = type->facets;
11270 do {
11271 switch (facet->type) {
11272 case XML_SCHEMA_FACET_LENGTH:
11273 case XML_SCHEMA_FACET_MINLENGTH:
11274 case XML_SCHEMA_FACET_MAXLENGTH:
11275 case XML_SCHEMA_FACET_WHITESPACE:
11276 /*
11277 * TODO: 2.5.1.2 List datatypes
11278 * The value of ·whiteSpace· is fixed to the value collapse.
11279 */
11280 case XML_SCHEMA_FACET_PATTERN:
11281 case XML_SCHEMA_FACET_ENUMERATION:
11282 break;
11283 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011284 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011285 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011286 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011287 /*
11288 * We could return, but it's nicer to report all
11289 * invalid facets.
11290 */
11291 ok = 0;
11292 }
11293 }
11294 facet = facet->next;
11295 } while (facet != NULL);
11296 if (ok == 0)
11297 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11298 /*
11299 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11300 * is a facet of the same kind in the {facets} of the {base type
11301 * definition} (call this BF),then the DF's {value} must be a valid
11302 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11303 */
11304 }
11305
11306
11307 }
11308 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11309 /*
11310 * 3.1 The {member type definitions} must all have {variety} of
11311 * atomic or list.
11312 */
11313 xmlSchemaTypeLinkPtr member;
11314
11315 member = type->memberTypes;
11316 while (member != NULL) {
11317 if (((member->type->flags &
11318 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11319 ((member->type->flags &
11320 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011321 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011322 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011323 NULL, type, NULL,
11324 "The member type %s is neither an atomic, nor a list type",
11325 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11326 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011327 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11328 }
11329 member = member->next;
11330 }
11331 /*
11332 * 3.3.1 If the {base type definition} is the ·simple ur-type
11333 * definition·
11334 */
11335 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11336 /*
11337 * 3.3.1.1 All of the {member type definitions} must have a
11338 * {final} which does not contain union.
11339 */
11340 member = type->memberTypes;
11341 while (member != NULL) {
11342 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11343 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011344 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011345 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011346 NULL, type, NULL,
11347 "The final of member type %s contains 'union'",
11348 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11349 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011350 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11351 }
11352 member = member->next;
11353 }
11354 /*
11355 * 3.3.1.2 The {facets} must be empty.
11356 */
11357 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011358 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011359 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011360 NULL, type, NULL,
11361 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011362 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11363 }
11364 } else {
11365 /*
11366 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11367 */
11368 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011369 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011370 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011371 NULL, type, NULL,
11372 "The base type %s is not a union type",
11373 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11374 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011375 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11376 }
11377 /*
11378 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11379 */
11380 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11381 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011382 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011383 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011384 NULL, type, NULL,
11385 "The final of its base type %s must not contain 'restriction'",
11386 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11387 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011388 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11389 }
11390 /*
11391 * 3.3.2.3 The {member type definitions}, in order, must be validly
11392 * derived from the corresponding type definitions in the {base
11393 * type definition}'s {member type definitions} given the empty set,
11394 * as defined in Type Derivation OK (Simple) (§3.14.6).
11395 */
11396 {
11397 xmlSchemaTypeLinkPtr baseMember;
11398
11399 /*
11400 * OPTIMIZE: if the type is restricting, it has no local defined
11401 * member types and inherits the member types of the base type;
11402 * thus a check for equality can be skipped.
11403 */
11404 /*
11405 * TODO: Even worse: I cannot see a scenario where a restricting
11406 * union simple type can have other member types as the member
11407 * types of it's base type. This check seems not necessary with
11408 * respect to the derivation process in libxml2.
11409 */
11410 if (type->memberTypes != NULL) {
11411 member = type->memberTypes;
11412 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11413 if ((member == NULL) && (baseMember != NULL)) {
11414 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011415 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011416 "Internal error: "
11417 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011418 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011419 "of member types in the base type\n",
11420 type->name, NULL);
11421 }
11422 while (member != NULL) {
11423 if (baseMember == NULL) {
11424 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011425 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011426 "Internal error: "
11427 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011428 "(3.3.2.3), union simple type '%s', unequal number "
11429 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011430 type->name, NULL);
11431 }
11432 if ((member->type != baseMember->type) &&
11433 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11434 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011435 xmlChar *strBMT = NULL, *strBT = NULL;
11436
11437 xmlSchemaPCustomErrExt(ctxt,
11438 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11439 NULL, type, NULL,
11440 "The member type %s is not validly derived from its "
11441 "corresponding member type %s of the base type %s",
11442 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11443 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11444 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11445 FREE_AND_NULL(str)
11446 FREE_AND_NULL(strBMT)
11447 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011448 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11449 }
11450 member = member->next;
11451 baseMember = baseMember->next;
11452 }
11453 }
11454 }
11455 /*
11456 * 3.3.2.4 Only pattern and enumeration facet components are
11457 * allowed among the {facets}.
11458 */
11459 if (type->facets != NULL) {
11460 xmlSchemaFacetPtr facet;
11461 int ok = 1;
11462
11463 facet = type->facets;
11464 do {
11465 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11466 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011467 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11468 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11469 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011470 ok = 0;
11471 }
11472 facet = facet->next;
11473 } while (facet != NULL);
11474 if (ok == 0)
11475 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11476
11477 }
11478 /*
11479 * TODO: 3.3.2.5 (facet derivation)
11480 */
11481 }
11482 }
11483
11484 return (0);
11485}
11486
11487/**
11488 * xmlSchemaCheckSRCSimpleType:
11489 * @ctxt: the schema parser context
11490 * @type: the simple type definition
11491 *
11492 * Checks crc-simple-type constraints.
11493 *
11494 * Returns 0 if the constraints are satisfied,
11495 * if not a positive error code and -1 on internal
11496 * errors.
11497 */
11498static int
11499xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11500 xmlSchemaTypePtr type)
11501{
11502 /*
11503 * NOTE: src-simple-type 2-4 are redundant, since the checks
11504 * were are done for the corresponding <restriction>, <list> and <union>
11505 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11506 * Maby this can be skipped in the future, if we get sure it's not needed.
11507 */
11508 if (type->subtypes == NULL) {
11509 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011510 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011511 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011512 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011513 type->name, NULL);
11514 return (-1);
11515 }
11516 /*
11517 * src-simple-type.1 The corresponding simple type definition, if any,
11518 * must satisfy the conditions set out in Constraints on Simple Type
11519 * Definition Schema Components (§3.14.6).
11520 */
11521 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11522 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11523 /*
11524 * TODO: Removed this, since it got annoying to get an
11525 * extra error report, if anything failed until now.
11526 * Enable this if needed.
11527 */
11528 /*
11529 xmlSchemaPErr(ctxt, type->node,
11530 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011531 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011532 "on simple type definitions.\n",
11533 type->name, NULL);
11534 */
11535 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11536 }
11537
11538 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11539 /*
11540 * src-simple-type.2 If the <restriction> alternative is chosen,
11541 * either it must have a base [attribute] or a <simpleType> among its
11542 * [children], but not both.
11543 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011544 /*
11545 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11546 * NOTE: This was removed, since this will be already handled
11547 * in the parse function for <restriction>.
11548 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011549 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11550 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11551 * an itemType [attribute] or a <simpleType> among its [children],
11552 * but not both.
11553 * NOTE: baseType is set to the local simple type definiton,
11554 * if existent, at parse time. This is a hack and not nice.
11555 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011556 /*
11557 * TODO: Remove this, and add the check to the parse function of <list>.
11558 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011559 if (((type->subtypes->base == NULL) &&
11560 (type->baseType == NULL)) ||
11561 ((type->subtypes->base != NULL) &&
11562 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011563 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011564 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011565 NULL, type, NULL,
11566 "Either the attribute 'itemType' or the <simpleType> child "
11567 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011568 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11569 }
11570
11571
11572 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11573 xmlSchemaTypeLinkPtr member;
11574 xmlSchemaTypePtr ancestor, anySimpleType;
11575
11576 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11577
11578 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11579 * the <union> alternative is chosen, there must not be any entries
11580 * in the memberTypes [attribute] at any depth which resolve to the
11581 * component corresponding to the <simpleType>.
11582 */
11583 member = type->memberTypes;
11584 while (member != NULL) {
11585 ancestor = member->type;
11586 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11587 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11588 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11589 if (ancestor == anySimpleType)
11590 break;
11591 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011592 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011593 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011594 NULL, type, NULL,
11595 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011596 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11597 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11598 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011599 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011600 * type as item type, which in turn has a list ST as member
11601 * type, we will assume this here as well, since this check
11602 * was not yet performed.
11603 */
11604
11605 }
11606 ancestor = ancestor->baseType;
11607 }
11608 member = member->next;
11609 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011610 }
11611
11612 return (0);
11613}
11614
William M. Brack2f2a6632004-08-20 23:09:47 +000011615#if 0 /* Not yet used code for CT schema validation */
11616static int
11617xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11618 const xmlChar * value,
11619 xmlSchemaTypePtr type,
11620 int fireErrors)
11621{
11622 int ret;
11623 /*
11624 * 3.14.4 Simple Type Definition Validation Rules
11625 * Validation Rule: String Valid
11626 */
11627 /*
11628 * 1 It is schema-valid with respect to that definition as defined
11629 * by Datatype Valid in [XML Schemas: Datatypes].
11630 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011631 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11632 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011633 return (ret);
11634 /*
11635 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11636 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11637 * the string must be a ·declared entity name·.
11638 */
11639 /*
11640 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11641 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11642 * then every whitespace-delimited substring of the string must be a ·declared
11643 * entity name·.
11644 */
11645 /*
11646 * 2.3 otherwise no further condition applies.
11647 */
11648
11649 return (0);
11650}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011651#endif
11652
William M. Brack2f2a6632004-08-20 23:09:47 +000011653
11654static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011655xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11656{
11657 if (vctxt->pctxt == NULL) {
11658 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11659 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11660 if (vctxt->pctxt == NULL) {
11661 xmlSchemaVErr(vctxt, NULL,
11662 XML_SCHEMAV_INTERNAL,
11663 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11664 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011665 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011666 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011667 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011668 /* TODO: Pass user data. */
11669 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11670 }
11671 return (0);
11672}
11673
11674static int
11675xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11676{
11677 if (ctxt->vctxt == NULL) {
11678 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11679 if (ctxt->vctxt == NULL) {
11680 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011681 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011682 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11683 "failed to create a temp. validation context.\n",
11684 NULL, NULL);
11685 return (-1);
11686 }
11687 /* TODO: Pass user data. */
11688 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11689 }
11690 return (0);
11691}
11692
11693/**
11694 * xmlSchemaCheckCOSValidDefault:
11695 * @ctxt: the schema parser context
11696 * @type: the simple type definition
11697 * @value: the default value
11698 * @node: an optional node (the holder of the value)
11699 *
11700 * Checks the "cos-valid-default" constraints.
11701 *
11702 * Returns 0 if the constraints are satisfied,
11703 * if not, a positive error code and -1 on internal
11704 * errors.
11705 */
11706static int
11707xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11708 xmlSchemaValidCtxtPtr vctxt,
11709 xmlSchemaTypePtr type,
11710 const xmlChar *value,
11711 xmlNodePtr node)
11712{
11713 int ret = 0;
11714
11715 /*
11716 * cos-valid-default:
11717 * Schema Component Constraint: Element Default Valid (Immediate)
11718 * For a string to be a valid default with respect to a type
11719 * definition the appropriate case among the following must be true:
11720 */
11721 /*
11722 * NOTE: This has to work without a given node (the holder of the
11723 * value), since it should work on the component, i.e. an underlying
11724 * DOM must not be mandatory.
11725 */
11726 if ((pctxt == NULL) || (vctxt == NULL)) {
11727 xmlSchemaPErr(pctxt, node,
11728 XML_SCHEMAP_INTERNAL,
11729 "Internal error: xmlSchemaCheckCOSValidDefault, "
11730 "bad arguments: the parser and/or validation context is "
11731 "missing.\n",
11732 NULL, NULL);
11733 return (-1);
11734 }
11735 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011736 /*
11737 * Complex type.
11738 *
11739 * 2.1 its {content type} must be a simple type definition or mixed.
11740 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011741 /*
11742 * TODO: Adjust this when the content type will be computed
11743 * correctly.
11744 */
11745 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11746 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11747 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11748 xmlSchemaPSimpleTypeErr(pctxt,
11749 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11750 NULL, NULL, node,
11751 type, NULL, NULL,
11752 "If the type of a constraint value is complex, its content "
11753 "type must be mixed or a simple type",
11754 NULL, NULL);
11755 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11756 }
11757 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011758 /*
11759 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11760 * particle must be ·emptiable· as defined by Particle Emptiable
11761 * (§3.9.6).
11762 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011763
William M. Brack2f2a6632004-08-20 23:09:47 +000011764 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011765 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011766 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011767 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011768 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011769 }
11770 /*
11771 * 1 If the type definition is a simple type definition, then the string
11772 * must be ·valid· with respect to that definition as defined by String
11773 * Valid (§3.14.4).
11774 *
11775 * AND
11776 *
11777 * 2.2.1 If the {content type} is a simple type definition, then the
11778 * string must be ·valid· with respect to that simple type definition
11779 * as defined by String Valid (§3.14.4).
11780 */
11781 vctxt->node = node;
11782 vctxt->cur = NULL;
11783 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11784 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11785 if (ret < 0) {
11786 xmlSchemaPErr(pctxt, node,
11787 /* NOTNICE: error code: This function will be used during
11788 * schema construction and xsi:type validation.
11789 */
11790 XML_SCHEMAP_INTERNAL,
11791 "Internal error: xmlSchemaCheckCOSValidDefault, "
11792 "while validating a value constaint value.\n",
11793 NULL, NULL);
11794
11795 }
11796 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011797}
11798
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011799#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011800/**
11801 * xmlSchemaGetSTContentOfCT:
11802 * @ctxt: the schema parser context
11803 * @type: the complex type definition
11804 *
11805 *
11806 * Returns the corresponding simple type for the content of
11807 * the complex type.
11808 */
11809static xmlSchemaTypePtr
11810xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11811 xmlSchemaTypePtr type)
11812{
11813 xmlSchemaTypePtr orig = type, anyType;
11814
11815 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11816 while ((type != NULL) && (type != anyType) &&
11817 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11818 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11819 return(type);
11820 type = type->baseType;
11821 }
11822 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011823 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011824 NULL, orig, NULL,
11825 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11826 "no simple type for the content of complex type '%s' could be "
11827 "computed", orig->name);
11828 return (NULL);
11829}
11830
11831
William M. Brack2f2a6632004-08-20 23:09:47 +000011832
William M. Brack2f2a6632004-08-20 23:09:47 +000011833
11834/**
11835 * xmlSchemaCheckCOSCTExtends:
11836 * @ctxt: the schema parser context
11837 * @type: the complex type definition
11838 *
11839 * Schema Component Constraint: Derivation Valid (Extension)
11840 *
11841 * Returns 0 if the constraints are satisfied, a positive
11842 * error code if not and -1 if an internal error occured.
11843 */
11844static int
11845xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11846 xmlSchemaTypePtr type)
11847{
11848 xmlSchemaTypePtr base;
11849 /*
11850 * 1 If the {base type definition} is a complex type definition,
11851 * then all of the following must be true:
11852 */
11853 base = type->baseType;
11854 if (base == NULL) {
11855 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011856 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011857 NULL, type, NULL,
11858 "Internal error: xmlSchemaCheckCOSCTExtends, "
11859 "the complex type '%s' has no base type", type->name);
11860 return (-1);
11861 }
11862 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11863 /*
11864 * 1.1 The {final} of the {base type definition} must not
11865 * contain extension.
11866 */
11867 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11868 xmlSchemaPCustomErr(ctxt,
11869 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11870 NULL, type, NULL,
11871 "The 'final' of the base type definition "
11872 "contains extension", NULL);
11873 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11874 }
11875 /*
11876 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11877 * of the complex type definition itself, that is, for every attribute
11878 * use in the {attribute uses} of the {base type definition}, there
11879 * must be an attribute use in the {attribute uses} of the complex
11880 * type definition itself whose {attribute declaration} has the same
11881 * {name}, {target namespace} and {type definition} as its attribute
11882 * declaration
11883 *
11884 * NOTE: This will be already satisfied by the way the attribute uses
11885 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11886 * is not needed.
11887 */
11888
11889 /*
11890 * 1.3 If it has an {attribute wildcard}, the complex type definition
11891 * must also have one, and the base type definition's {attribute
11892 * wildcard}'s {namespace constraint} must be a subset of the complex
11893 * type definition's {attribute wildcard}'s {namespace constraint},
11894 * as defined by Wildcard Subset (§3.10.6).
11895 *
11896 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11897 * this check is not needed.
11898 */
11899
11900 /*
11901 * 1.4 One of the following must be true:
11902 *
11903 * 1.4.1 The {content type} of the {base type definition} and the
11904 * {content type} of the complex type definition itself must be the same
11905 * simple type definition
11906 */
11907
11908
11909
11910 } else {
11911 /*
11912 * 2 If the {base type definition} is a simple type definition,
11913 * then all of the following must be true:
11914 */
11915 /*
11916 * 2.1 The {content type} must be the same simple type definition.
11917 */
11918 /*
11919 * 2.2 The {final} of the {base type definition} must not contain
11920 * extension
11921 */
11922 }
11923
11924}
11925
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011926static int
11927xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11928 xmlSchemaTypePtr type)
11929{
11930 xmlSchemaTypePtr base, content;
11931 int OK = 0;
11932
11933 /*
11934 * TODO: Adjust the error codes here, as I used
11935 * XML_SCHEMAP_SRC_CT_1 only yet.
11936 */
11937 /*
11938 * Schema Representation Constraint:
11939 * Complex Type Definition Representation OK
11940 */
11941 base = type->baseType;
11942 if (base == NULL) {
11943 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11944 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11945 type->name);
11946 return (-1);
11947 }
11948
11949 if (type->subtypes != NULL) {
11950 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11951 if IS_COMPLEX_TYPE(base) {
11952 /*
11953 * 1 If the <complexContent> alternative is chosen, the type definition
11954 * ·resolved· to by the ·actual value· of the base [attribute]
11955 * must be a complex type definition;
11956 */
11957 xmlSchemaPCustomErr(ctxt,
11958 XML_SCHEMAP_SRC_CT_1,
11959 NULL, type, NULL,
11960 "The base type is not a complex type", NULL);
11961 return (XML_SCHEMAP_SRC_CT_1);
11962 }
11963 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11964
11965 if IS_SIMPLE_TYPE(base) {
11966 if (type->flags &
11967 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11968 /*
11969 * 2.1.3 only if the <extension> alternative is also
11970 * chosen, a simple type definition.
11971 */
11972 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11973 xmlSchemaPCustomErr(ctxt,
11974 XML_SCHEMAP_SRC_CT_1,
11975 NULL, type, NULL,
11976 "A complex type (simple content) cannot restrict "
11977 "an other simple type",
11978 NULL);
11979 return (XML_SCHEMAP_SRC_CT_1);
11980 }
11981 OK = 1;
11982
11983 } else { /* if IS_SIMPLE_TYPE(base) */
11984 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11985 /*
11986 * 2.1.2 only if the <restriction> alternative is also
11987 * chosen, a complex type definition whose {content type}
11988 * is mixed and a particle emptyable.
11989 */
11990 /*
11991 * FIXME TODO: Check for *empiable particle* is missing.
11992 */
11993 if ((type->flags &
11994 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11995 xmlSchemaPCustomErr(ctxt,
11996 XML_SCHEMAP_SRC_CT_1,
11997 NULL, type, NULL,
11998 "A complex type (simple content) cannot "
11999 "extend an other complex type which has a "
12000 "content type of: 'mixed' and emptiable particle",
12001 NULL);
12002 return (XML_SCHEMAP_SRC_CT_1);
12003 }
12004 /*
12005 * NOTE: This will be fired as well, if the base type
12006 * is *'anyType'*.
12007 * NOTE: type->subtypes->subtypes will be the
12008 * <restriction> item.
12009 */
12010 if (type->subtypes->subtypes == NULL) {
12011 /* Yes, this is paranoid programming. */
12012 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12013 NULL, type, NULL,
12014 "Internal error: xmlSchemaCheckSRCCT, "
12015 "'%s', <simpleContent> has no <restriction>",
12016 type->name);
12017 return (-1);
12018 }
12019 /*
12020 * 2.2 If clause 2.1.2 above is satisfied, then there
12021 * must be a <simpleType> among the [children] of
12022 * <restriction>.
12023 */
12024 if (type->subtypes->subtypes->type !=
12025 XML_SCHEMA_TYPE_SIMPLE) {
12026 /* TODO: Change error code to ..._SRC_CT_2_2. */
12027 xmlSchemaPCustomErr(ctxt,
12028 XML_SCHEMAP_SRC_CT_1,
12029 NULL, type, NULL,
12030 "A <simpleType> is expected among the children "
12031 "of <restriction>", NULL);
12032 return (XML_SCHEMAP_SRC_CT_1);
12033 }
12034 OK = 1;
12035 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12036 /*
12037 * 2.1.1 a complex type definition whose {content type} is a
12038 * simple type definition;
12039 */
12040 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12041 xmlSchemaPCustomErr(ctxt,
12042 XML_SCHEMAP_SRC_CT_1,
12043 NULL, type, NULL,
12044 "A complex type (simple content) cannot "
12045 "be derived from the complex type '%s'",
12046 base->name);
12047 return (XML_SCHEMAP_SRC_CT_1);
12048 }
12049 content = base->contentTypeDef;
12050 if (content == NULL) {
12051 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12052 NULL, type, NULL,
12053 "Internal error: xmlSchemaCheckSRCCT, "
12054 "'%s', base type has no content type",
12055 type->name);
12056 return (-1);
12057 }
12058 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12059 xmlSchemaPCustomErr(ctxt,
12060 XML_SCHEMAP_SRC_CT_1,
12061 NULL, type, NULL,
12062 "A complex type (simple content) cannot "
12063 "be derived from the complex type '%s'",
12064 base->name);
12065 return (XML_SCHEMAP_SRC_CT_1);
12066 }
12067 }
12068 }
12069 }
12070 }
12071 /*
12072 * TODO: 3 The corresponding complex type definition component must
12073 * satisfy the conditions set out in Constraints on Complex Type
12074 * Definition Schema Components (§3.4.6);
12075 *
12076 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12077 * above for {attribute wildcard} is satisfied, the intensional
12078 * intersection must be expressible, as defined in Attribute Wildcard
12079 * Intersection (§3.10.6).
12080 */
12081
12082}
William M. Brack2f2a6632004-08-20 23:09:47 +000012083#endif
12084
Daniel Veillard01fa6152004-06-29 17:04:39 +000012085/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012086 * xmlSchemaGroupDefFixup:
12087 * @typeDecl: the schema model group definition
12088 * @ctxt: the schema parser context
12089 *
12090 * Fixes model group definitions.
12091 */
12092static void
12093xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12094 xmlSchemaParserCtxtPtr ctxt,
12095 const xmlChar * name ATTRIBUTE_UNUSED)
12096{
12097 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12098 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12099 xmlSchemaTypePtr groupDef;
12100 /*
12101 * Resolve the reference.
12102 */
12103 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12104 group->refNs);
12105 if (groupDef == NULL) {
12106 xmlSchemaPResCompAttrErr(ctxt,
12107 XML_SCHEMAP_SRC_RESOLVE,
12108 NULL, group, NULL,
12109 "ref", group->ref, group->refNs,
12110 XML_SCHEMA_TYPE_GROUP, NULL);
12111 return;
12112 }
12113 group->subtypes = groupDef;
12114 }
12115}
12116
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012117#if 0 /* Enable when the content type will be computed. */
12118static int
12119xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12120 xmlSchemaTypePtr type)
12121{
12122 xmlSchemaTypePtr base, res = NULL;
12123
12124 base = type->baseType;
12125 if (base == NULL) {
12126 xmlSchemaPCustomErr(ctxt,
12127 XML_SCHEMAP_INTERNAL,
12128 NULL, type, NULL,
12129 "Internal error: xmlSchemaGetContentType, "
12130 "the complex type '%s' has no base type", type->name);
12131 return (-1);
12132 }
12133 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12134 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12135 xmlSchemaTypePtr start;
12136 /*
12137 * Effective 'mixed'.
12138 */
12139 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12140 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12141 /*
12142 * Effective content.
12143 */
12144 if (IS_ANYTYPE(base))
12145 start = type;
12146 else
12147 start = type->subtypes;
12148
12149 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12150 xmlSchemaTypePtr baseContentItem;
12151
12152 /*
12153 * Complex type with simple content.
12154 */
12155 if IS_COMPLEX_TYPE(base) {
12156 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12157 /*
12158 * Summary: a complex type (simple content) can *restrict*
12159 * a complex type with the following content type:
12160 * 1. 'mixed' and an emptiable particle
12161 * 2. simple type
12162 */
12163 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12164 /*
12165 * 2 if the {content type} of the base type is mixed and a
12166 * particle which is ·emptiable·,
12167 * [...]
12168 * then starting from the simple type definition
12169 * corresponding to the <simpleType> among the [children]
12170 * of <restriction> (**which must be present**)
12171 *
12172 * FIXME TODO: Handle "emptiable particle".
12173 */
12174 res = type->subtypes->subtypes;
12175 if (res == NULL) {
12176 xmlSchemaPCustomErr(ctxt,
12177 XML_SCHEMAP_INTERNAL,
12178 NULL, type, NULL,
12179 "Internal error: xmlSchemaGetContentType, "
12180 "CT '%s' (restricting): <simpleContent> has no "
12181 "<restriction>",
12182 type->name);
12183 return (-1);
12184 }
12185
12186 res->subtypes;
12187 if (res == NULL) {
12188 xmlSchemaPCustomErr(ctxt,
12189 XML_SCHEMAP_INTERNAL,
12190 NULL, type, NULL,
12191 "Internal error: xmlSchemaGetContentType, "
12192 "CT '%s' (restricting): <restriction> has no "
12193 "mandatory <simpleType>",
12194 type->name);
12195 return (-1);
12196 }
12197 } else {
12198 baseContentItem = base->contentTypeDef;
12199 if (baseContentItem == NULL) {
12200 xmlSchemaPCustomErr(ctxt,
12201 XML_SCHEMAP_INTERNAL,
12202 NULL, type, NULL,
12203 "Internal error: xmlSchemaGetContentType, "
12204 "CT '%s' (restricting), the base type has no "
12205 "content type", type->name);
12206 return (-1);
12207 }
12208 if IS_SIMPLE_TYPE(baseContentItem) {
12209 /*
12210 * 1 If the base type is a complex type whose own
12211 * {content type} is a simple type and the <restriction>
12212 * alternative is chosen
12213 */
12214 /* type->subtypes->subtypes will be the restriction item.*/
12215 res = type->subtypes->subtypes;
12216 if (res == NULL) {
12217 xmlSchemaPCustomErr(ctxt,
12218 XML_SCHEMAP_INTERNAL,
12219 NULL, type, NULL,
12220 "Internal error: xmlSchemaGetContentType, "
12221 "CT '%s' (restricting): <simpleType> has no "
12222 "<restriction>", type->name);
12223 return (-1);
12224 }
12225 /*
12226 * 1.1 the simple type definition corresponding to the
12227 * <simpleType> among the [children] of <restriction>if
12228 * there is one;
12229 */
12230 res = res->subtypes;
12231 if (res == NULL) {
12232 /*
12233 * 1.2 otherwise the {content type}
12234 * of the base type .
12235 */
12236 res = baseContentItem;
12237 }
12238 }
12239 }
12240 /*
12241 * SPECIAL TODO: If *restricting* the spec wants us to
12242 * create an *additional* simple type which restricts the
12243 * located simple type; we won't do this yet, and look how
12244 * far we get with it.
12245 */
12246 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12247 /*
12248 * Summary: a complex type (simple content) can *extend*
12249 * only a complex base with a simple type as content.
12250 */
12251 /*
12252 * 3 If the type definition ·resolved· to by the ·actual
12253 * value· of the base [attribute] is a complex type
12254 * definition (whose own {content type} *must be* a simple
12255 * type definition, see below) and the *<extension>*
12256 * alternative is chosen, then the {content type} of that
12257 * complex type definition;
12258 */
12259 res = base->contentTypeDef;
12260 if (res == NULL) {
12261 xmlSchemaPCustomErr(ctxt,
12262 XML_SCHEMAP_INTERNAL,
12263 NULL, type, NULL,
12264 "Internal error: xmlSchemaGetContentType, "
12265 "CT '%s' (extending), the base type has no content "
12266 "type", type->name);
12267 return (-1);
12268 }
12269 if (! IS_SIMPLE_TYPE(res)) {
12270 xmlSchemaPCustomErr(ctxt,
12271 XML_SCHEMAP_INTERNAL,
12272 NULL, type, NULL,
12273 "Internal error: xmlSchemaGetContentType, "
12274 "CT '%s' (extending), the content type of the "
12275 "base is not a simple type", type->name);
12276 return (-1);
12277 }
12278 }
12279 } else /* if IS_COMPLEX_TYPE(base) */
12280 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12281 /*
12282 * 4 otherwise (the type definition ·resolved· to by the
12283 * ·actual value· of the base [attribute] is a simple type
12284 * definition and the <extension> alternative is chosen),
12285 * then that simple type definition.
12286 */
12287 res = base;
12288 }
12289 type->contentTypeDef = res;
12290 if (res == NULL) {
12291 xmlSchemaPCustomErr(ctxt,
12292 XML_SCHEMAP_INTERNAL,
12293 NULL, type, NULL,
12294 "Internal error: xmlSchemaGetContentType, "
12295 "'%s', the content type could not be determined",
12296 type->name);
12297 return (-1);
12298 }
12299
12300 }
12301
12302}
12303#endif
12304
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012305/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012306 * xmlSchemaTypeFixup:
12307 * @typeDecl: the schema type definition
12308 * @ctxt: the schema parser context
12309 *
12310 * Fixes the content model of the type.
12311 */
12312static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012313xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012314 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012315{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012316 xmlSchemaTypePtr ctxtType;
12317
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012318 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012319 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012320 /*
12321 * Do not allow the following types to be typefixed, prior to
12322 * the corresponding simple/complex types.
12323 */
12324 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012325 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012326 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12327 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12328 case XML_SCHEMA_TYPE_UNION:
12329 case XML_SCHEMA_TYPE_RESTRICTION:
12330 case XML_SCHEMA_TYPE_EXTENSION:
12331 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012332 default:
12333 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012334 }
12335 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012336 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012337 name = item->name;
12338 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12339 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012340 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012341 if (item->subtypes != NULL) {
12342 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012343 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012344 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012345 NULL);
12346 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012347 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012348 XML_SCHEMA_CONTENT_SIMPLE;
12349 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012350 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012351 break;
12352 }
12353 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012354 xmlSchemaTypePtr base = NULL;
12355
12356 ctxt->ctxtType->flags |=
12357 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012358 if (item->baseType != NULL)
12359 base = item->baseType;
12360 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012361 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012362 xmlSchemaGetType(ctxt->schema, item->base,
12363 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012365 xmlSchemaPResCompAttrErr(ctxt,
12366 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012367 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012368 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12369 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012370 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012371 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012372 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012373 xmlSchemaTypeFixup(base, ctxt, NULL);
12374 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012375 }
12376 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012377 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12378 /*
12379 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012380 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012381 /*
12382 * Content type.
12383 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012384 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012385 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012386 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12387 else if ((item->subtypes->subtypes == NULL) &&
12388 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012389 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012390 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012391 XML_SCHEMA_TYPE_SEQUENCE)))
12392 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012393 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12394 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012395 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012396 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012397 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012398 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012399 else {
12400 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012401 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012402 XML_SCHEMA_CONTENT_ELEMENTS;
12403 }
12404 } else {
12405 /*
12406 * SimpleType restriction.
12407 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012408 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012409 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012410 break;
12411 }
12412 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012413 xmlSchemaTypePtr base = NULL;
12414 xmlSchemaContentType explicitContentType;
12415
12416 /*
12417 * An extension does exist on a complexType only.
12418 */
12419 ctxt->ctxtType->flags |=
12420 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012421 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012422 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012423 xmlSchemaPCustomErr(ctxt,
12424 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012425 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012426 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012427 return;
12428 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012429 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012430 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012431 xmlSchemaGetType(ctxt->schema, item->base,
12432 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012433 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012434 xmlSchemaPResCompAttrErr(ctxt,
12435 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012436 NULL, item, item->node,
12437 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012438 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012439 } else if (base->contentType ==
12440 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012441 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012442 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012443 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012444 }
12445 /*
12446 * The type definition ·resolved· to by the ·actual
12447 * value· of the base [attribute]
12448 */
12449 ctxt->ctxtType->baseType = base;
12450 /*
12451 * TODO: This one is still needed for computation of
12452 * the content model by xmlSchemaBuildAContentModel.
12453 * Try to get rid of it.
12454 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012455 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012456 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012457 if ((item->subtypes != NULL) &&
12458 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12459 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012460
12461 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012462 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012463 /* 1.1.1 */
12464 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012465 else if ((item->subtypes->subtypes == NULL) &&
12466 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012467 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012468 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012469 XML_SCHEMA_TYPE_SEQUENCE)))
12470 /* 1.1.2 */
12471 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012472 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012473 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012474 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012475 /* 1.1.3 */
12476 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12477 if (base != NULL) {
12478 /* It will be reported later, if the base is missing. */
12479 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12480 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012481 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012482 } else if (base->contentType ==
12483 XML_SCHEMA_CONTENT_EMPTY) {
12484 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012485 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012486 XML_SCHEMA_CONTENT_ELEMENTS;
12487 } else {
12488 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012489 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012490 XML_SCHEMA_CONTENT_ELEMENTS;
12491 }
12492 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012493 break;
12494 }
12495 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012496 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012497 ctxt->ctxtType = item;
12498 /*
12499 * Start with an empty content-type type.
12500 */
12501 if (item->subtypes == NULL)
12502 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12503
12504 if ((item->subtypes == NULL) ||
12505 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012506 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012507 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012508 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12509 /*
12510 * This case is understood as shorthand for complex
12511 * content restricting the ur-type definition, and
12512 * the details of the mappings should be modified as
12513 * necessary.
12514 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012515 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12516 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012517 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012518 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012519 * Assume that we inherit the content-type type
12520 * from 'anyType', which is 'mixed' and a particle
12521 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012522 */
12523 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012524 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012525 /*
12526 * Fixup the sub components.
12527 */
12528 if ((item->subtypes != NULL) &&
12529 (item->subtypes->contentType ==
12530 XML_SCHEMA_CONTENT_UNKNOWN)) {
12531 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012532 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012533 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12534 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12535 } else if (item->subtypes != NULL) {
12536 /*
12537 * Use the content-type type of the model groups
12538 * defined, if 'mixed' is not set. If 'mixed' is set
12539 * it will expand the content-type by allowing character
12540 * content to appear.
12541 */
12542 item->contentType =
12543 item->subtypes->contentType;
12544 }
12545 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012546 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012547 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012548 break;
12549 }
12550 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012551 if (item->subtypes == NULL) {
12552 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12553 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12554 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012555 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012556 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012557 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12558 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012559 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012560 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012561 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012562 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012563 if (item->subtypes != NULL)
12564 item->contentType =
12565 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012566 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012567 /*
12568 * Removed due to implementation of the build of attribute uses.
12569 */
12570 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012571 if (item->attributes == NULL)
12572 item->attributes =
12573 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012574 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012575 }
12576 break;
12577 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012578 case XML_SCHEMA_TYPE_SIMPLE:
12579 /*
12580 * Simple Type Definition Schema Component
12581 *
12582 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012583 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012584 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12585 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012586 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012587 ctxt->ctxtType = item;
12588 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012589 }
12590 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012591 if ((item->baseType != NULL) &&
12592 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012593 XML_SCHEMA_CONTENT_UNKNOWN)) {
12594 /* OPTIMIZE: Actually this one will never by hit, since
12595 * the base type is already type-fixed in <restriction>.
12596 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012597 ctxt->ctxtType = item;
12598 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012599 }
12600 /* Base type:
12601 * 2 If the <list> or <union> alternative is chosen,
12602 * then the ·simple ur-type definition·.
12603 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012604 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012605 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012606 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12607 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12608 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012609 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012610 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12611 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12612 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012613 XML_SCHEMA_TYPE_RESTRICTION) {
12614 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12615
12616 /*
12617 * Variety
12618 * If the <restriction> alternative is chosen, then the
12619 * {variety} of the {base type definition}.
12620 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012621 if (item->baseType != NULL) {
12622 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012623 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012624 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12625 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012626 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012627 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12628 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012629 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012630 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012631 /*
12632 * Schema Component Constraint: Simple Type Restriction
12633 * (Facets)
12634 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12635 * applied beforehand.
12636 *
12637 * 3 The {facets} of R are the union of S and the {facets}
12638 * of B, eliminating duplicates. To eliminate duplicates,
12639 * when a facet of the same kind occurs in both S and the
12640 * {facets} of B, the one in the {facets} of B is not
12641 * included, with the exception of enumeration and pattern
12642 * facets, for which multiple occurrences with distinct values
12643 * are allowed.
12644 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012645 if (item->baseType->facetSet != NULL) {
12646 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012647 if (last != NULL)
12648 while (last->next != NULL)
12649 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012650 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012651 for (; cur != NULL; cur = cur->next) {
12652 /*
12653 * Base patterns won't be add here:
12654 * they are ORed in a type and
12655 * ANDed in derived types. This will
12656 * happed at validation level by
12657 * walking the base axis of the type.
12658 */
12659 if (cur->facet->type ==
12660 XML_SCHEMA_FACET_PATTERN)
12661 continue;
12662 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012663 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012664 (cur->facet->type !=
12665 XML_SCHEMA_FACET_PATTERN) &&
12666 (cur->facet->type !=
12667 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012668 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012669 do {
12670 if (cur->facet->type ==
12671 facet->facet->type)
12672 break;
12673 facet = facet->next;
12674 } while (facet != NULL);
12675 }
12676 if (facet == NULL) {
12677 facet = (xmlSchemaFacetLinkPtr)
12678 xmlMalloc(sizeof(xmlSchemaFacetLink));
12679 if (facet == NULL) {
12680 xmlSchemaPErrMemory(ctxt,
12681 "fixing simpleType", NULL);
12682 return;
12683 }
12684 facet->facet = cur->facet;
12685 facet->next = NULL;
12686 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012687 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012688 else
12689 last->next = facet;
12690 last = facet;
12691 }
12692 }
12693 }
12694 }
12695 }
12696 /*
12697 * Check constraints.
12698 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012699 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012700 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012701 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012702 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012703 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012704 case XML_SCHEMA_TYPE_ALL:
12705 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012706 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012707 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012708 case XML_SCHEMA_TYPE_GROUP:
12709 /*
12710 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12711 */
12712 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012713 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012714 xmlSchemaParseListRefFixup(item, ctxt);
12715 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012716 break;
12717 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012718 xmlSchemaParseUnionRefCheck(item, ctxt);
12719 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012720 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012721 case XML_SCHEMA_TYPE_BASIC:
12722 case XML_SCHEMA_TYPE_ANY:
12723 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012724 case XML_SCHEMA_TYPE_UR:
12725 case XML_SCHEMA_TYPE_ELEMENT:
12726 case XML_SCHEMA_TYPE_ATTRIBUTE:
12727 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012728 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012729 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012730 case XML_SCHEMA_FACET_MININCLUSIVE:
12731 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12732 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12733 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12734 case XML_SCHEMA_FACET_TOTALDIGITS:
12735 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12736 case XML_SCHEMA_FACET_PATTERN:
12737 case XML_SCHEMA_FACET_ENUMERATION:
12738 case XML_SCHEMA_FACET_WHITESPACE:
12739 case XML_SCHEMA_FACET_LENGTH:
12740 case XML_SCHEMA_FACET_MAXLENGTH:
12741 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012742 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12743 if (item->subtypes != NULL)
12744 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012745 break;
12746 }
12747 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012748#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012749 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012750 xmlGenericError(xmlGenericErrorContext,
12751 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012752 item->node->doc->URL,
12753 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012754 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012755 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012756 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012757 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012758 case XML_SCHEMA_CONTENT_SIMPLE:
12759 xmlGenericError(xmlGenericErrorContext, "simple\n");
12760 break;
12761 case XML_SCHEMA_CONTENT_ELEMENTS:
12762 xmlGenericError(xmlGenericErrorContext, "elements\n");
12763 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012764 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012765 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12766 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012767 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012768 xmlGenericError(xmlGenericErrorContext, "empty\n");
12769 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012770 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012771 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12772 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012773 /* Removed, since not used. */
12774 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012775 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012776 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12777 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012778 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012779 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012780 xmlGenericError(xmlGenericErrorContext, "basic\n");
12781 break;
12782 default:
12783 xmlGenericError(xmlGenericErrorContext,
12784 "not registered !!!\n");
12785 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012786 }
12787#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012788}
12789
12790/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012791 * xmlSchemaCheckFacet:
12792 * @facet: the facet
12793 * @typeDecl: the schema type definition
12794 * @ctxt: the schema parser context or NULL
12795 * @name: name of the type
12796 *
12797 * Checks the default values types, especially for facets
12798 *
12799 * Returns 0 if okay or -1 in cae of error
12800 */
12801int
12802xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012803 xmlSchemaTypePtr typeDecl,
12804 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012805{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012806 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012807 int ret = 0, reuseValCtxt = 0;
12808
Daniel Veillardce682bc2004-11-05 17:22:25 +000012809 if ((facet == NULL) || (typeDecl == NULL))
12810 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012811 /*
12812 * TODO: will the parser context be given if used from
12813 * the relaxNG module?
12814 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012815
12816 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012817 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012818 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012819 }
12820 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012821 case XML_SCHEMA_FACET_MININCLUSIVE:
12822 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12823 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012824 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12825 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012826 /*
12827 * Okay we need to validate the value
12828 * at that point.
12829 */
12830 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012831 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012832
12833 /* 4.3.5.5 Constraints on enumeration Schema Components
12834 * Schema Component Constraint: enumeration valid restriction
12835 * It is an ·error· if any member of {value} is not in the
12836 * ·value space· of {base type definition}.
12837 *
12838 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12839 * The value ·must· be in the
12840 * ·value space· of the ·base type·.
12841 */
12842 /*
12843 * This function is intended to deliver a compiled value
12844 * on the facet. In XML Schemas the type holding a facet,
12845 * cannot be a built-in type. Thus to ensure that other API
12846 * calls (relaxng) do work, if the given type is a built-in
12847 * type, we will assume that the given built-in type *is
12848 * already* the base type.
12849 */
12850 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12851 base = typeDecl->baseType;
12852 if (base == NULL) {
12853 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012854 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012855 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012856 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012857 typeDecl->name, NULL);
12858 return (-1);
12859 }
12860 } else
12861 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012862 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012863 * This avoids perseverative creation of the
12864 * validation context if a parser context is
12865 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012866 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012867 if (ctxt != NULL) {
12868 reuseValCtxt = 1;
12869 if (ctxt->vctxt == NULL) {
12870 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12871 return (-1);
12872 }
12873 vctxt = ctxt->vctxt;
12874 } else {
12875 vctxt = xmlSchemaNewValidCtxt(NULL);
12876 if (vctxt == NULL) {
12877 xmlSchemaPErr(ctxt, typeDecl->node,
12878 XML_SCHEMAP_INTERNAL,
12879 "Internal error: xmlSchemaCheckFacet, "
12880 "creating a new validation context.\n",
12881 NULL, NULL);
12882 return (-1);
12883 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012884 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012885
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012886 vctxt->node = facet->node;
12887 vctxt->cur = NULL;
12888 /*
12889 * NOTE: This call does not check the content nodes,
12890 * since they are not available:
12891 * facet->node is just the node holding the facet
12892 * definition, *not* the attribute holding the *value*
12893 * of the facet.
12894 */
12895 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12896 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012897 facet->val = vctxt->value;
12898 vctxt->value = NULL;
12899 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012900 /* error code */
12901 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012902 xmlSchemaPErrExt(ctxt, facet->node,
12903 XML_SCHEMAP_INVALID_FACET,
12904 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012905 "Type definition '%s': The value '%s' of the "
12906 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012907 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012908 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012909 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012910 }
12911 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012912 } else if (ret < 0) {
12913 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012914 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012915 NULL, NULL, NULL,
12916 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012917 "failed to validate the value '%s' name of the "
12918 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012919 facet->value,
12920 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12921 base->name, NULL, NULL);
12922 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012923 }
12924 if (reuseValCtxt == 0)
12925 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012926 break;
12927 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012928 case XML_SCHEMA_FACET_PATTERN:
12929 facet->regexp = xmlRegexpCompile(facet->value);
12930 if (facet->regexp == NULL) {
12931 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012932 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012933 "Type definition '%s': The value '%s' of the "
12934 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012935 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012936 ret = -1;
12937 }
12938 break;
12939 case XML_SCHEMA_FACET_TOTALDIGITS:
12940 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12941 case XML_SCHEMA_FACET_LENGTH:
12942 case XML_SCHEMA_FACET_MAXLENGTH:
12943 case XML_SCHEMA_FACET_MINLENGTH:{
12944 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012945
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012946 tmp =
12947 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12948 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012949 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012950 if (tmp != 0) {
12951 /* error code */
12952 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012953 xmlSchemaPErrExt(ctxt, facet->node,
12954 XML_SCHEMAP_INVALID_FACET_VALUE,
12955 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012956 "Type definition '%s': The value '%s' of the "
12957 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012958 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012959 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012960 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012961 }
12962 ret = -1;
12963 }
12964 break;
12965 }
12966 case XML_SCHEMA_FACET_WHITESPACE:{
12967 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12968 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12969 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12970 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12971 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12972 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12973 } else {
12974 if (ctxt != NULL) {
12975 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012976 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012977 "Type definition '%s': The value '%s' of the "
12978 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012979 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012980 }
12981 ret = -1;
12982 }
12983 }
12984 default:
12985 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012986 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012987 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012988}
12989
12990/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012991 * xmlSchemaCheckDefaults:
12992 * @typeDecl: the schema type definition
12993 * @ctxt: the schema parser context
12994 *
12995 * Checks the default values types, especially for facets
12996 */
12997static void
12998xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012999 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013000{
Daniel Veillard4255d502002-04-16 15:50:10 +000013001 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013002 name = typeDecl->name;
13003 /*
13004 * NOTE: It is intended to use the facets list, instead
13005 * of facetSet.
13006 */
13007 if (typeDecl->facets != NULL) {
13008 xmlSchemaFacetPtr facet = typeDecl->facets;
13009
13010 while (facet != NULL) {
13011 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
13012 facet = facet->next;
13013 }
13014 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013015}
13016
13017/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013018 * xmlSchemaGetCircModelGrDefRef:
13019 * @ctxtGr: the searched model group
13020 * @list: the list of model groups to be processed
13021 *
13022 * This one is intended to be used by
13023 * xmlSchemaCheckGroupDefCircular only.
13024 *
13025 * Returns the circular model group definition reference, otherwise NULL.
13026 */
13027static xmlSchemaTypePtr
13028xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13029 xmlSchemaTypePtr gr)
13030{
13031 xmlSchemaTypePtr circ = NULL;
13032 int marked;
13033 /*
13034 * We will search for an model group reference which
13035 * references the context model group definition.
13036 */
13037 while (gr != NULL) {
13038 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13039 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13040 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13041 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13042 (gr->subtypes != NULL)) {
13043 marked = 0;
13044 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13045 (gr->ref != NULL)) {
13046 if (gr->subtypes == ctxtGrDef)
13047 return (gr);
13048 else if (gr->subtypes->flags &
13049 XML_SCHEMAS_TYPE_MARKED) {
13050 gr = gr->next;
13051 continue;
13052 } else {
13053 /*
13054 * Mark to avoid infinite recursion on
13055 * circular references not yet examined.
13056 */
13057 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13058 marked = 1;
13059 }
13060 if (gr->subtypes->subtypes != NULL)
13061 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13062 gr->subtypes->subtypes);
13063 /*
13064 * Unmark the visited model group definition.
13065 */
13066 if (marked)
13067 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13068 if (circ != NULL)
13069 return (circ);
13070 } else {
13071 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13072 (xmlSchemaTypePtr) gr->subtypes);
13073 if (circ != NULL)
13074 return (circ);
13075 }
13076
13077 }
13078 gr = gr->next;
13079 }
13080 return (NULL);
13081}
13082
13083/**
13084 * xmlSchemaCheckGroupDefCircular:
13085 * attrGr: the model group definition
13086 * @ctxt: the parser context
13087 * @name: the name
13088 *
13089 * Checks for circular references to model group definitions.
13090 */
13091static void
13092xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13093 xmlSchemaParserCtxtPtr ctxt,
13094 const xmlChar * name ATTRIBUTE_UNUSED)
13095{
13096 /*
13097 * Schema Component Constraint: Model Group Correct
13098 * 2 Circular groups are disallowed. That is, within the {particles}
13099 * of a group there must not be at any depth a particle whose {term}
13100 * is the group itself.
13101 */
13102 /*
13103 * NOTE: "gr->subtypes" holds the referenced group.
13104 */
13105 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13106 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13107 (modelGrDef->subtypes == NULL))
13108 return;
13109 else {
13110 xmlSchemaTypePtr circ;
13111
13112 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13113 if (circ != NULL) {
13114 /*
13115 * TODO: Report the referenced attr group as QName.
13116 */
13117 xmlSchemaPCustomErr(ctxt,
13118 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13119 NULL, NULL, circ->node,
13120 "Circular reference to the model group definition '%s' "
13121 "defined", modelGrDef->name);
13122 /*
13123 * NOTE: We will cut the reference to avoid further
13124 * confusion of the processor.
13125 * TODO: SPEC: Does the spec define how to process here?
13126 */
13127 circ->subtypes = NULL;
13128 }
13129 }
13130}
13131
13132
13133/**
13134 * xmlSchemaGetCircAttrGrRef:
13135 * @ctxtGr: the searched attribute group
13136 * @attr: the current attribute list to be processed
13137 *
13138 * This one is intended to be used by
13139 * xmlSchemaCheckSRCAttributeGroupCircular only.
13140 *
13141 * Returns the circular attribute grou reference, otherwise NULL.
13142 */
13143static xmlSchemaAttributeGroupPtr
13144xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
13145 xmlSchemaAttributePtr attr)
13146{
13147 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13148 int marked;
13149 /*
13150 * We will search for an attribute group reference which
13151 * references the context attribute group.
13152 */
13153 while (attr != NULL) {
13154 marked = 0;
13155 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13156 gr = (xmlSchemaAttributeGroupPtr) attr;
13157 if (gr->refItem != NULL) {
13158 if (gr->refItem == ctxtGr)
13159 return (gr);
13160 else if (gr->refItem->flags &
13161 XML_SCHEMAS_ATTRGROUP_MARKED) {
13162 attr = attr->next;
13163 continue;
13164 } else {
13165 /*
13166 * Mark as visited to avoid infinite recursion on
13167 * circular references not yet examined.
13168 */
13169 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
13170 marked = 1;
13171 }
13172 }
13173 if (gr->attributes != NULL)
13174 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
13175 /*
13176 * Unmark the visited group's attributes.
13177 */
13178 if (marked)
13179 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
13180 if (circ != NULL)
13181 return (circ);
13182 }
13183 attr = attr->next;
13184 }
13185 return (NULL);
13186}
13187
13188/**
13189 * xmlSchemaCheckSRCAttributeGroupCircular:
13190 * attrGr: the attribute group definition
13191 * @ctxt: the parser context
13192 * @name: the name
13193 *
13194 * Checks for circular references of attribute groups.
13195 */
13196static void
13197xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
13198 xmlSchemaParserCtxtPtr ctxt,
13199 const xmlChar * name ATTRIBUTE_UNUSED)
13200{
13201 /*
13202 * Schema Representation Constraint:
13203 * Attribute Group Definition Representation OK
13204 * 3 Circular group reference is disallowed outside <redefine>.
13205 * That is, unless this element information item's parent is
13206 * <redefine>, then among the [children], if any, there must
13207 * not be an <attributeGroup> with ref [attribute] which resolves
13208 * to the component corresponding to this <attributeGroup>. Indirect
13209 * circularity is also ruled out. That is, when QName resolution
13210 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13211 * any <attributeGroup>s with a ref [attribute] among the [children],
13212 * it must not be the case that a ·QName· is encountered at any depth
13213 * which resolves to the component corresponding to this <attributeGroup>.
13214 */
13215 /*
13216 * Only global components can be referenced.
13217 */
13218 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
13219 (attrGr->attributes == NULL))
13220 return;
13221 else {
13222 xmlSchemaAttributeGroupPtr circ;
13223
13224 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
13225 if (circ != NULL) {
13226 /*
13227 * TODO: Report the referenced attr group as QName.
13228 */
13229 xmlSchemaPCustomErr(ctxt,
13230 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13231 NULL, NULL, circ->node,
13232 "Circular reference to the attribute group '%s' "
13233 "defined", attrGr->name);
13234 /*
13235 * NOTE: We will cut the reference to avoid further
13236 * confusion of the processor.
13237 * BADSPEC: The spec should define how to process in this case.
13238 */
13239 circ->attributes = NULL;
13240 circ->refItem = NULL;
13241 }
13242 }
13243}
13244
13245/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013246 * xmlSchemaAttrGrpFixup:
13247 * @attrgrpDecl: the schema attribute definition
13248 * @ctxt: the schema parser context
13249 * @name: the attribute name
13250 *
13251 * Fixes finish doing the computations on the attributes definitions
13252 */
13253static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013254xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013255 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013256{
13257 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013258 name = attrgrp->name;
13259 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013260 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013261 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013262 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013263
Daniel Veillardc0826a72004-08-10 14:17:33 +000013264 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13265 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013266 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013267 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013268 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013269 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13270 "ref", attrgrp->ref, attrgrp->refNs,
13271 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013272 return;
13273 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013274 attrgrp->refItem = ref;
13275 /*
13276 * Check for self reference!
13277 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013278 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013279 attrgrp->attributes = ref->attributes;
13280 attrgrp->attributeWildcard = ref->attributeWildcard;
13281 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013282}
13283
13284/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013285 * xmlSchemaAttrCheckValConstr:
13286 * @item: an schema attribute declaration/use
13287 * @ctxt: a schema parser context
13288 * @name: the name of the attribute
13289 *
13290 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013291 *
13292 * Fixes finish doing the computations on the attributes definitions
13293 */
13294static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013295xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13296 xmlSchemaParserCtxtPtr ctxt,
13297 const xmlChar * name ATTRIBUTE_UNUSED)
13298{
13299
13300 /*
13301 * a-props-correct
13302 * Schema Component Constraint: Attribute Declaration Properties Correct
13303 *
13304 * 2 if there is a {value constraint}, the canonical lexical
13305 * representation of its value must be ·valid· with respect
13306 * to the {type definition} as defined in String Valid (§3.14.4).
13307 */
13308
13309 if (item->defValue != NULL) {
13310 int ret;
13311 xmlNodePtr node;
13312 xmlSchemaTypePtr type;
13313
13314 if (item->subtypes == NULL) {
13315 xmlSchemaPErr(ctxt, item->node,
13316 XML_SCHEMAP_INTERNAL,
13317 "Internal error: xmlSchemaCheckAttrValConstr, "
13318 "type is missing... skipping validation of "
13319 "value constraint", NULL, NULL);
13320 return;
13321 }
13322
13323 /*
13324 * TODO: Try to avoid creating a new context.
13325 * TODO: This all is not very performant.
13326 */
13327 type = item->subtypes;
13328 /*
13329 * Ensure there's validation context.
13330 */
13331 if (ctxt->vctxt == NULL) {
13332 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13333 xmlSchemaPErr(ctxt, item->node,
13334 XML_SCHEMAP_INTERNAL,
13335 "Internal error: xmlSchemaCheckAttrValConstr, "
13336 "creating a new validation context.\n",
13337 NULL, NULL);
13338 return;
13339 }
13340 }
13341
13342 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13343 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13344 else
13345 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13346 ctxt->vctxt->node = node;
13347 ctxt->vctxt->cur = NULL;
13348 /*
13349 * NOTE: This call does not check the content nodes,
13350 * since they are not available:
13351 * facet->node is just the node holding the facet
13352 * definition, *not* the attribute holding the *value*
13353 * of the facet.
13354 */
13355 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13356 item->defValue, 0, 1, 1, 0);
13357 if (ret == 0) {
13358 /*
13359 * Store the computed value.
13360 */
13361 item->defVal = ctxt->vctxt->value;
13362 ctxt->vctxt->value = NULL;
13363 } else if (ret > 0) {
13364 if (ctxt != NULL) {
13365 xmlSchemaPSimpleTypeErr(ctxt,
13366 XML_SCHEMAP_A_PROPS_CORRECT_2,
13367 NULL, NULL, node,
13368 type, NULL, item->defValue,
13369 NULL, NULL, NULL);
13370 }
13371 } else if (ret < 0) {
13372 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13373 NULL, NULL, node,
13374 "Internal error: xmlSchemaAttrCheckValConstr, "
13375 "failed to validate the value constraint of the "
13376 "attribute decl/use against the type '%s'",
13377 type->name);
13378 }
13379 }
13380}
13381
13382#if 0 /* Not used yet. */
13383static int
13384xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13385 xmlSchemaElementPtr edecl)
13386{
13387 /*
13388 * TODO: 1 The values of the properties of an element declaration must be as
13389 * described in the property tableau in The Element Declaration Schema
13390 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13391 */
13392 /*
13393 * 2 If there is a {value constraint}, the canonical lexical
13394 * representation of its value must be ·valid· with respect to the {type
13395 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13396 *
13397 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13398 */
13399 /*
13400 * 3 If there is a non-·absent· {substitution group affiliation},
13401 * then {scope} must be global.
13402 *
13403 * NOTE: This is done in xmlSchemaParseElement.
13404 * TODO: Move it to this layer here.
13405 */
13406 /*
13407 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13408 * of the element declaration must be validly derived from the {type
13409 * definition} of the {substitution group affiliation}, given the value
13410 * of the {substitution group exclusions} of the {substitution group
13411 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13412 * (if the {type definition} is complex) or as defined in
13413 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13414 * simple).
13415 */
13416 /*
13417 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13418 * is or is derived from ID then there must not be a {value constraint}.
13419 * Note: The use of ID as a type definition for elements goes beyond
13420 * XML 1.0, and should be avoided if backwards compatibility is desired
13421 */
13422 /*
13423 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13424 * be possible to return to an element declaration by repeatedly following
13425 * the {substitution group affiliation} property.
13426 */
13427}
13428#endif
13429
13430/**
13431 * xmlSchemaCheckElemValConstr:
13432 * @item: an schema element declaration/particle
13433 * @ctxt: a schema parser context
13434 * @name: the name of the attribute
13435 *
13436 * Validates the value constraints of an element declaration.
13437 *
13438 * Fixes finish doing the computations on the element declarations.
13439 */
13440static void
13441xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13442 xmlSchemaParserCtxtPtr ctxt,
13443 const xmlChar * name ATTRIBUTE_UNUSED)
13444{
13445 if (decl->value != NULL) {
13446 int ret;
13447 xmlNodePtr node = NULL;
13448 xmlSchemaTypePtr type;
13449
13450 /*
13451 * 2 If there is a {value constraint}, the canonical lexical
13452 * representation of its value must be ·valid· with respect to the {type
13453 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13454 */
13455 if (decl->subtypes == NULL) {
13456 xmlSchemaPErr(ctxt, decl->node,
13457 XML_SCHEMAP_INTERNAL,
13458 "Internal error: xmlSchemaCheckElemValConstr, "
13459 "type is missing... skipping validation of "
13460 "the value constraint", NULL, NULL);
13461 return;
13462 }
13463 /*
13464 * Ensure there's a validation context.
13465 */
13466 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13467 return;
13468
13469 type = decl->subtypes;
13470
13471 if (decl->node != NULL) {
13472 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13473 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13474 else
13475 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13476 }
13477 ctxt->vctxt->node = node;
13478 ctxt->vctxt->cur = NULL;
13479 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13480 node);
13481 if (ret == 0) {
13482 /*
13483 * Consume the computed value.
13484 */
13485 decl->defVal = ctxt->vctxt->value;
13486 ctxt->vctxt->value = NULL;
13487 } else if (ret < 0) {
13488 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13489 NULL, NULL, node,
13490 "Internal error: xmlSchemaElemCheckValConstr, "
13491 "failed to validate the value constraint of the "
13492 "element declaration '%s'",
13493 decl->name);
13494 }
13495 }
13496}
13497
13498/**
13499 * xmlSchemaAttrFixup:
13500 * @item: an schema attribute declaration/use.
13501 * @ctxt: a schema parser context
13502 * @name: the name of the attribute
13503 *
13504 * Fixes finish doing the computations on attribute declarations/uses.
13505 */
13506static void
13507xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13508 xmlSchemaParserCtxtPtr ctxt,
13509 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013510{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013511 /*
13512 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013513 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013514 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 /*
13516 * The simple type definition corresponding to the <simpleType> element
13517 * information item in the [children], if present, otherwise the simple
13518 * type definition ·resolved· to by the ·actual value· of the type
13519 * [attribute], if present, otherwise the ·simple ur-type definition·.
13520 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013521 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013522 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013523 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13524 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013525 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013526 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013527 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013528
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013529 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13530 item->typeNs);
13531 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013532 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013534 NULL, (xmlSchemaTypePtr) item, item->node,
13535 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013536 XML_SCHEMA_TYPE_SIMPLE, NULL);
13537 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013538 item->subtypes = type;
13539
13540 } else if (item->ref != NULL) {
13541 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013542
Daniel Veillardc0826a72004-08-10 14:17:33 +000013543 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013544 * We have an attribute use here; assign the referenced
13545 * attribute declaration.
13546 */
13547 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013548 * TODO: Evaluate, what errors could occur if the declaration is not
13549 * found. It might be possible that the "typefixup" might crash if
13550 * no ref declaration was found.
13551 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013552 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13553 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013554 xmlSchemaPResCompAttrErr(ctxt,
13555 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013556 NULL, (xmlSchemaTypePtr) item, item->node,
13557 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013558 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013559 return;
13560 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013561 item->refDecl = decl;
13562 xmlSchemaAttrFixup(decl, ctxt, NULL);
13563
13564 item->subtypes = decl->subtypes;
13565 /*
13566 * Attribute Use Correct
13567 * au-props-correct.2: If the {attribute declaration} has a fixed
13568 * {value constraint}, then if the attribute use itself has a
13569 * {value constraint}, it must also be fixed and its value must match
13570 * that of the {attribute declaration}'s {value constraint}.
13571 */
13572 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13573 (item->defValue != NULL)) {
13574 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13575 (!xmlStrEqual(item->defValue, decl->defValue))) {
13576 xmlSchemaPCustomErr(ctxt,
13577 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13578 NULL, NULL, item->node,
13579 "The value constraint must be fixed "
13580 "and match the referenced attribute "
13581 "declarations's value constraint '%s'",
13582 decl->defValue);
13583 }
13584 /*
13585 * FUTURE: One should change the values of the attr. use
13586 * if ever validation should be attempted even if the
13587 * schema itself was not fully valid.
13588 */
13589 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013590 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013591 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13592 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013593}
13594
13595/**
13596 * xmlSchemaParse:
13597 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013598 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013599 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013600 * XML Shema struture which can be used to validate instances.
13601 * *WARNING* this interface is highly subject to change
13602 *
13603 * Returns the internal XML Schema structure built from the resource or
13604 * NULL in case of error
13605 */
13606xmlSchemaPtr
13607xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13608{
13609 xmlSchemaPtr ret = NULL;
13610 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013611 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013612 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013613
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013614 /*
13615 * This one is used if the schema to be parsed was specified via
13616 * the API; i.e. not automatically by the validated instance document.
13617 */
13618
Daniel Veillard4255d502002-04-16 15:50:10 +000013619 xmlSchemaInitTypes();
13620
Daniel Veillard6045c902002-10-09 21:13:59 +000013621 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013622 return (NULL);
13623
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013624 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013625 ctxt->counter = 0;
13626 ctxt->container = NULL;
13627
13628 /*
13629 * First step is to parse the input document into an DOM/Infoset
13630 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013631 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013632 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13633 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013634 if (doc == NULL) {
13635 xmlSchemaPErr(ctxt, NULL,
13636 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013637 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013638 ctxt->URL, NULL);
13639 return (NULL);
13640 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013641 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013642 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13643 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013644 if (doc == NULL) {
13645 xmlSchemaPErr(ctxt, NULL,
13646 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013647 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013648 NULL, NULL);
13649 return (NULL);
13650 }
13651 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013652 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013653 } else if (ctxt->doc != NULL) {
13654 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013655 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013656 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013657 xmlSchemaPErr(ctxt, NULL,
13658 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013659 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013660 NULL, NULL);
13661 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013662 }
13663
13664 /*
13665 * Then extract the root and Schema parse it
13666 */
13667 root = xmlDocGetRootElement(doc);
13668 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013669 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13670 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013671 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013672 if (!preserve) {
13673 xmlFreeDoc(doc);
13674 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013675 return (NULL);
13676 }
13677
13678 /*
13679 * Remove all the blank text nodes
13680 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013681 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013682
13683 /*
13684 * Then do the parsing for good
13685 */
13686 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013687 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013688 if (!preserve) {
13689 xmlFreeDoc(doc);
13690 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013691 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013692 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013693 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013694 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013695 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013696 ctxt->ctxtType = NULL;
13697 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013698 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013699 * Then fixup all attributes declarations
13700 */
13701 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13702
13703 /*
13704 * Then fixup all attributes group declarations
13705 */
13706 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13707 ctxt);
13708
13709 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013710 * Check attribute groups for circular references.
13711 */
13712 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13713 xmlSchemaCheckAttributeGroupCircular, ctxt);
13714
13715 /*
13716 * Then fixup all model group definitions.
13717 */
13718 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013719
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013720 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013721 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013722 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013723 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013724
13725 /*
13726 * Then fix references of element declaration; apply constraints.
13727 */
13728 xmlHashScanFull(ret->elemDecl,
13729 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013730
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013731 /*
13732 * Check model groups defnitions for circular references.
13733 */
13734 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13735 xmlSchemaCheckGroupDefCircular, ctxt);
13736
Daniel Veillard4255d502002-04-16 15:50:10 +000013737 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013738 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013739 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013740 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013741 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013742
13743 /*
13744 * Then check the defaults part of the type like facets values
13745 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013746 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000013747
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013748 /*
13749 * Validate the value constraint of attribute declarations/uses.
13750 */
13751 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13752
13753 /*
13754 * Validate the value constraint of element declarations.
13755 */
13756 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13757
Daniel Veillardc0826a72004-08-10 14:17:33 +000013758
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013759 if (ctxt->nberrors != 0) {
13760 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013761 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013762 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013763 return (ret);
13764}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013765
Daniel Veillard4255d502002-04-16 15:50:10 +000013766/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013767 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013768 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013769 * @err: the error callback
13770 * @warn: the warning callback
13771 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013772 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013773 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013774 */
13775void
13776xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013777 xmlSchemaValidityErrorFunc err,
13778 xmlSchemaValidityWarningFunc warn, void *ctx)
13779{
Daniel Veillard4255d502002-04-16 15:50:10 +000013780 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013781 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013782 ctxt->error = err;
13783 ctxt->warning = warn;
13784 ctxt->userData = ctx;
13785}
13786
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013787/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013788 * xmlSchemaGetParserErrors:
13789 * @ctxt: a XMl-Schema parser context
13790 * @err: the error callback result
13791 * @warn: the warning callback result
13792 * @ctx: contextual data for the callbacks result
13793 *
13794 * Get the callback information used to handle errors for a parser context
13795 *
13796 * Returns -1 in case of failure, 0 otherwise
13797 */
13798int
13799xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13800 xmlSchemaValidityErrorFunc * err,
13801 xmlSchemaValidityWarningFunc * warn, void **ctx)
13802{
13803 if (ctxt == NULL)
13804 return(-1);
13805 if (err != NULL)
13806 *err = ctxt->error;
13807 if (warn != NULL)
13808 *warn = ctxt->warning;
13809 if (ctx != NULL)
13810 *ctx = ctxt->userData;
13811 return(0);
13812}
13813
13814/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013815 * xmlSchemaFacetTypeToString:
13816 * @type: the facet type
13817 *
13818 * Convert the xmlSchemaTypeType to a char string.
13819 *
13820 * Returns the char string representation of the facet type if the
13821 * type is a facet and an "Internal Error" string otherwise.
13822 */
13823static const char *
13824xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13825{
13826 switch (type) {
13827 case XML_SCHEMA_FACET_PATTERN:
13828 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013829 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013830 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013831 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013832 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013833 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013834 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013835 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013836 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013837 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013838 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013839 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013840 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013841 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013842 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013843 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013844 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013845 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013846 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013847 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013848 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013849 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013850 return ("fractionDigits");
13851 default:
13852 break;
13853 }
13854 return ("Internal Error");
13855}
13856
Daniel Veillardc0826a72004-08-10 14:17:33 +000013857
Daniel Veillardc0826a72004-08-10 14:17:33 +000013858
13859static int
13860xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13861{
13862 xmlSchemaTypePtr anc;
13863
13864 /*
13865 * The normalization type can be changed only for types which are derived
13866 * from xsd:string.
13867 */
13868 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013869 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013870 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013871 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
13872 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013873 else {
13874 /*
13875 * For all ·atomic· datatypes other than string (and types ·derived·
13876 * by ·restriction· from it) the value of whiteSpace is fixed to
13877 * collapse
13878 */
13879 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13880 }
13881 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13882 /*
13883 * For list types the facet "whiteSpace" is fixed to "collapse".
13884 */
13885 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13886 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13887 return (-1);
13888 } else if (type->facetSet != NULL) {
13889 xmlSchemaTypePtr anyST;
13890 xmlSchemaFacetLinkPtr lin;
13891
13892 /*
13893 * Atomic types.
13894 */
13895 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13896 anc = type->baseType;
13897 do {
13898 /*
13899 * For all ·atomic· datatypes other than string (and types ·derived·
13900 * by ·restriction· from it) the value of whiteSpace is fixed to
13901 * collapse
13902 */
13903 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13904 (anc->builtInType == XML_SCHEMAS_STRING)) {
13905
13906 lin = type->facetSet;
13907 do {
13908 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13909 if (lin->facet->whitespace ==
13910 XML_SCHEMAS_FACET_COLLAPSE) {
13911 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13912 } else if (lin->facet->whitespace ==
13913 XML_SCHEMAS_FACET_REPLACE) {
13914 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13915 } else
13916 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13917 break;
13918 }
13919 lin = lin->next;
13920 } while (lin != NULL);
13921 break;
13922 }
13923 anc = anc->baseType;
13924 } while (anc != anyST);
13925 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13926 }
13927 return (-1);
13928}
13929
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013930/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013931 * xmlSchemaValidateFacetsInternal:
13932 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013933 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013934 * @facets: the list of facets to check
13935 * @value: the lexical repr of the value to validate
13936 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013937 * @fireErrors: if 0, only internal errors will be fired;
13938 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013939 *
13940 * Check a value against all facet conditions
13941 *
13942 * Returns 0 if the element is schemas valid, a positive error code
13943 * number otherwise and -1 in case of internal or API error.
13944 */
13945static int
13946xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013947 xmlSchemaTypePtr type,
13948 const xmlChar * value,
13949 unsigned long length,
13950 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013951{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013952 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013953 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013954 xmlSchemaTypePtr biType; /* The build-in type. */
13955 xmlSchemaTypePtr tmpType;
13956 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013957 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013958 xmlSchemaFacetPtr facet;
13959 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013960
Daniel Veillardc0826a72004-08-10 14:17:33 +000013961#ifdef DEBUG_UNION_VALIDATION
13962 printf("Facets of type: '%s'\n", (const char *) type->name);
13963 printf(" fireErrors: %d\n", fireErrors);
13964#endif
13965
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013966 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013967 /*
13968 * NOTE: Do not jump away, if the facetSet of the given type is
13969 * empty: until now, "pattern" facets of the *base types* need to
13970 * be checked as well.
13971 */
13972 biType = type->baseType;
13973 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13974 biType = biType->baseType;
13975 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013976 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013977 "Internal error: xmlSchemaValidateFacetsInternal, "
13978 "the base type axis of the given type '%s' does not resolve to "
13979 "a built-in type.\n",
13980 type->name, NULL);
13981 return (-1);
13982 }
13983
13984 if (type->facetSet != NULL) {
13985 facetLink = type->facetSet;
13986 while (facetLink != NULL) {
13987 facet = facetLink->facet;
13988 /*
13989 * Skip the pattern "whiteSpace": it is used to
13990 * format the character content beforehand.
13991 */
13992 switch (facet->type) {
13993 case XML_SCHEMA_FACET_WHITESPACE:
13994 case XML_SCHEMA_FACET_PATTERN:
13995 case XML_SCHEMA_FACET_ENUMERATION:
13996 break;
13997 case XML_SCHEMA_FACET_LENGTH:
13998 case XML_SCHEMA_FACET_MINLENGTH:
13999 case XML_SCHEMA_FACET_MAXLENGTH:
14000 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14001 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
14002 value, length, 0);
14003 len = length;
14004 } else
14005 ret = xmlSchemaValidateLengthFacet(biType, facet,
14006 value, ctxt->value, &len);
14007 break;
14008 default:
14009 ret = xmlSchemaValidateFacet(biType, facet, value,
14010 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014011 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014012 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014013 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014014 "Internal error: xmlSchemaValidateFacetsInternal, "
14015 "validating facet of type '%s'.\n",
14016 type->name, NULL);
14017 break;
14018 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014019 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014020 type, facet, NULL, NULL, NULL, NULL);
14021 }
14022
14023 facetLink = facetLink->next;
14024 }
14025 if (ret >= 0) {
14026 /*
14027 * Process enumerations.
14028 */
14029 retFacet = 0;
14030 facetLink = type->facetSet;
14031 while (facetLink != NULL) {
14032 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14033 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14034 value, ctxt->value);
14035 if (retFacet <= 0)
14036 break;
14037 }
14038 facetLink = facetLink->next;
14039 }
14040 if (retFacet > 0) {
14041 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14042 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014043 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014044 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14045 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014046 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014047 "Internal error: xmlSchemaValidateFacetsInternal, "
14048 "validating facet of type '%s'.\n",
14049 BAD_CAST "enumeration", NULL);
14050 ret = -1;
14051 }
14052 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014053 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014054 if (ret >= 0) {
14055 /*
14056 * Process patters. Pattern facets are ORed at type level
14057 * and ANDed if derived. Walk the base type axis.
14058 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014059 tmpType = type;
14060 facet = NULL;
14061 do {
14062 retFacet = 0;
14063 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014064 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014065 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14066 continue;
14067 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14068 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014069 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014070 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014071 else if (retFacet < 0) {
14072 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14073 "Internal error: xmlSchemaValidateFacetsInternal, "
14074 "validating 'pattern' facet '%s' of type '%s'.\n",
14075 facetLink->facet->value, tmpType->name);
14076 ret = -1;
14077 break;
14078 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014079 /* Save the last non-validating facet. */
14080 facet = facetLink->facet;
14081 }
14082 if (retFacet != 0)
14083 break;
14084 tmpType = tmpType->baseType;
14085 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014086 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014087 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14088 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014089 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014090 NULL, NULL, NULL, NULL);
14091 }
14092 }
14093 }
14094
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014095 return (ret);
14096}
14097
Daniel Veillard4255d502002-04-16 15:50:10 +000014098/************************************************************************
14099 * *
14100 * Simple type validation *
14101 * *
14102 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000014103
Daniel Veillard4255d502002-04-16 15:50:10 +000014104
14105/************************************************************************
14106 * *
14107 * DOM Validation code *
14108 * *
14109 ************************************************************************/
14110
Daniel Veillard4255d502002-04-16 15:50:10 +000014111static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014112 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000014113 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014114static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014115 xmlSchemaTypePtr type,
14116 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000014117
Daniel Veillard3646d642004-06-02 19:19:14 +000014118
14119/**
14120 * xmlSchemaFreeAttrStates:
14121 * @state: a list of attribute states
14122 *
14123 * Free the given list of attribute states
14124 *
14125 */
14126static void
14127xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
14128{
14129 xmlSchemaAttrStatePtr tmp;
14130 while (state != NULL) {
14131 tmp = state;
14132 state = state->next;
14133 xmlFree(tmp);
14134 }
14135}
14136
Daniel Veillard4255d502002-04-16 15:50:10 +000014137/**
14138 * xmlSchemaRegisterAttributes:
14139 * @ctxt: a schema validation context
14140 * @attrs: a list of attributes
14141 *
14142 * Register the list of attributes as the set to be validated on that element
14143 *
14144 * Returns -1 in case of error, 0 otherwise
14145 */
14146static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014147xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
14148{
Daniel Veillard3646d642004-06-02 19:19:14 +000014149 xmlSchemaAttrStatePtr tmp;
14150
14151 ctxt->attr = NULL;
14152 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014153 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014154 if ((attrs->ns != NULL) &&
14155 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
14156 attrs = attrs->next;
14157 continue;
14158 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014159 tmp = (xmlSchemaAttrStatePtr)
14160 xmlMalloc(sizeof(xmlSchemaAttrState));
14161 if (tmp == NULL) {
14162 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
14163 return (-1);
14164 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014165 tmp->attr = attrs;
14166 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
14167 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014168 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014169 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014170 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000014171 else
14172 ctxt->attrTop->next = tmp;
14173 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014174 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014175 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014176 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014177}
14178
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014179#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000014180/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014181 * xmlSchemaValidateCheckNodeList
14182 * @nodelist: the list of nodes
14183 *
14184 * Check the node list is only made of text nodes and entities pointing
14185 * to text nodes
14186 *
14187 * Returns 1 if true, 0 if false and -1 in case of error
14188 */
14189static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014190xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
14191{
Daniel Veillard4255d502002-04-16 15:50:10 +000014192 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014193 if (nodelist->type == XML_ENTITY_REF_NODE) {
14194 TODO /* implement recursion in the entity content */
14195 }
14196 if ((nodelist->type != XML_TEXT_NODE) &&
14197 (nodelist->type != XML_COMMENT_NODE) &&
14198 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000014199 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014200 return (0);
14201 }
14202 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014203 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014204 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014205}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014206#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014207
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014208static void
14209xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14210{
14211 int i, nbItems;
14212 xmlSchemaTypePtr item, *items;
14213
14214
14215 /*
14216 * During the Assemble of the schema ctxt->curItems has
14217 * been filled with the relevant new items. Fix those up.
14218 */
14219 nbItems = ctxt->assemble->nbItems;
14220 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14221
14222 for (i = 0; i < nbItems; i++) {
14223 item = items[i];
14224 switch (item->type) {
14225 case XML_SCHEMA_TYPE_ATTRIBUTE:
14226 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14227 break;
14228 case XML_SCHEMA_TYPE_ELEMENT:
14229 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14230 NULL, NULL, NULL);
14231 break;
14232 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14233 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14234 ctxt, NULL);
14235 break;
14236 case XML_SCHEMA_TYPE_GROUP:
14237 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14238 default:
14239 break;
14240 }
14241 }
14242 /*
14243 * Circularity checks.
14244 */
14245 for (i = 0; i < nbItems; i++) {
14246 item = items[i];
14247 switch (item->type) {
14248 case XML_SCHEMA_TYPE_GROUP:
14249 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14250 break;
14251 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14252 xmlSchemaCheckAttributeGroupCircular(
14253 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14254 break;
14255 default:
14256 break;
14257 }
14258 }
14259 /*
14260 * Fixup for all other item.
14261 * TODO: Hmm, not sure if starting from complex/simple types,
14262 * all subsequent items will be reached.
14263 */
14264 for (i = 0; i < nbItems; i++) {
14265 item = items[i];
14266 switch (item->type) {
14267 case XML_SCHEMA_TYPE_SIMPLE:
14268 case XML_SCHEMA_TYPE_COMPLEX:
14269 xmlSchemaTypeFixup(item, ctxt, NULL);
14270 break;
14271 default:
14272 break;
14273 }
14274 }
14275 /*
14276 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014277 * hold by simple type components only (and
14278 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014279 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014280 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014281 for (i = 0; i < nbItems; i++) {
14282 item = items[i];
14283 switch (item->type) {
14284 case XML_SCHEMA_TYPE_SIMPLE:
14285 case XML_SCHEMA_TYPE_COMPLEX:
14286 xmlSchemaCheckDefaults(item, ctxt, NULL);
14287 break;
14288 default:
14289 break;
14290 }
14291 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014292 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014293 /*
14294 * Build the content model for complex types.
14295 */
14296 for (i = 0; i < nbItems; i++) {
14297 item = items[i];
14298 switch (item->type) {
14299 case XML_SCHEMA_TYPE_COMPLEX:
14300 xmlSchemaBuildContentModel(item, ctxt, NULL);
14301 break;
14302 default:
14303 break;
14304 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014305 }
14306 /*
14307 * Validate value contraint values.
14308 */
14309 for (i = 0; i < nbItems; i++) {
14310 item = items[i];
14311 switch (item->type) {
14312 case XML_SCHEMA_TYPE_ATTRIBUTE:
14313 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14314 break;
14315 case XML_SCHEMA_TYPE_ELEMENT:
14316 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14317 break;
14318 default:
14319 break;
14320 }
14321 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014322}
14323
14324/**
14325 * xmlSchemaAssembleByLocation:
14326 * @pctxt: a schema parser context
14327 * @vctxt: a schema validation context
14328 * @schema: the existing schema
14329 * @node: the node that fired the assembling
14330 * @nsName: the namespace name of the new schema
14331 * @location: the location of the schema
14332 *
14333 * Expands an existing schema by an additional schema.
14334 *
14335 * Returns 0 if the new schema is correct, a positive error code
14336 * number otherwise and -1 in case of an internal or API error.
14337 */
14338static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014339xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14340 xmlSchemaPtr schema,
14341 xmlNodePtr node,
14342 const xmlChar *nsName,
14343 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014344{
14345 const xmlChar *targetNs, *oldtns;
14346 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014347 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014348 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014349 xmlSchemaParserCtxtPtr pctxt;
14350
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014351 /*
14352 * This should be used:
14353 * 1. on <import>(s)
14354 * 2. if requested by the validated instance
14355 * 3. if requested via the API
14356 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014357 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014358 return (-1);
14359 /*
14360 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014361 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014362 if ((vctxt->pctxt == NULL) &&
14363 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14364 xmlSchemaVErr(vctxt, node,
14365 XML_SCHEMAV_INTERNAL,
14366 "Internal error: xmlSchemaAssembleByLocation, "
14367 "failed to create a temp. parser context.\n",
14368 NULL, NULL);
14369 return (-1);
14370 }
14371 pctxt = vctxt->pctxt;
14372 /*
14373 * Set the counter to produce unique names for anonymous items.
14374 */
14375 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014376 /*
14377 * Acquire the schema document.
14378 */
14379 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14380 nsName, location, &doc, &targetNs, 0);
14381 if (ret != 0) {
14382 if (doc != NULL)
14383 xmlFreeDoc(doc);
14384 } else if (doc != NULL) {
14385 docElem = xmlDocGetRootElement(doc);
14386 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014387 * Create new assemble info.
14388 */
14389 if (pctxt->assemble == NULL) {
14390 pctxt->assemble = xmlSchemaNewAssemble();
14391 if (pctxt->assemble == NULL) {
14392 xmlSchemaVErrMemory(vctxt,
14393 "Memory error: xmlSchemaAssembleByLocation, "
14394 "allocating assemble info", NULL);
14395 xmlFreeDoc(doc);
14396 return (-1);
14397 }
14398 }
14399 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014400 * Save and reset the context & schema.
14401 */
14402 oldflags = schema->flags;
14403 oldtns = schema->targetNamespace;
14404 olddoc = schema->doc;
14405
14406 xmlSchemaClearSchemaDefaults(schema);
14407 schema->targetNamespace = targetNs;
14408 /* schema->nbCurItems = 0; */
14409 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014410 pctxt->ctxtType = NULL;
14411 pctxt->parentItem = NULL;
14412
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014413 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14414 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014415 xmlSchemaPostSchemaAssembleFixup(pctxt);
14416 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014417 * Set the counter of items.
14418 */
14419 schema->counter = pctxt->counter;
14420 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014421 * Free the list of assembled components.
14422 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014423 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014424 /*
14425 * Restore the context & schema.
14426 */
14427 schema->flags = oldflags;
14428 schema->targetNamespace = oldtns;
14429 schema->doc = olddoc;
14430 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014431 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014432 return (ret);
14433}
14434
14435/**
14436 * xmlSchemaAssembleByXSIAttr:
14437 * @vctxt: a schema validation context
14438 * @xsiAttr: an xsi attribute
14439 * @noNamespace: whether a schema with no target namespace is exptected
14440 *
14441 * Expands an existing schema by an additional schema using
14442 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14443 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14444 * must be set to 1.
14445 *
14446 * Returns 0 if the new schema is correct, a positive error code
14447 * number otherwise and -1 in case of an internal or API error.
14448 */
14449static int
14450xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14451 xmlAttrPtr xsiAttr,
14452 int noNamespace)
14453{
14454 xmlChar *value;
14455 const xmlChar *cur, *end;
14456 const xmlChar *nsname = NULL, *location;
14457 int count = 0;
14458 int ret = 0;
14459
14460 if (xsiAttr == NULL) {
14461 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14462 NULL, NULL,
14463 "Internal error: xmlSchemaAssembleByXSIAttr, "
14464 "bad arguments", NULL);
14465 return (-1);
14466 }
14467 /*
14468 * Parse the value; we will assume an even number of values
14469 * to be given (this is how Xerces and XSV work).
14470 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014471 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014472 cur = value;
14473 do {
14474 if (noNamespace != 1) {
14475 /*
14476 * Get the namespace name.
14477 */
14478 while (IS_BLANK_CH(*cur))
14479 cur++;
14480 end = cur;
14481 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14482 end++;
14483 if (end == cur)
14484 break;
14485 count++;
14486 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14487 cur = end;
14488 }
14489 /*
14490 * Get the URI.
14491 */
14492 while (IS_BLANK_CH(*cur))
14493 cur++;
14494 end = cur;
14495 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14496 end++;
14497 if (end == cur)
14498 break;
14499 count++;
14500 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014501 cur = end;
14502 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014503 xsiAttr->parent, nsname, location);
14504 if (ret == -1) {
14505 xmlSchemaVCustomErr(vctxt,
14506 XML_SCHEMAV_INTERNAL,
14507 (xmlNodePtr) xsiAttr, NULL,
14508 "Internal error: xmlSchemaAssembleByXSIAttr, "
14509 "assembling schemata", NULL);
14510 if (value != NULL)
14511 xmlFree(value);
14512 return (-1);
14513 }
14514 } while (*cur != 0);
14515 if (value != NULL)
14516 xmlFree(value);
14517 return (ret);
14518}
14519
14520/**
14521 * xmlSchemaAssembleByXSIElem:
14522 * @vctxt: a schema validation context
14523 * @elem: an element node possibly holding xsi attributes
14524 * @noNamespace: whether a schema with no target namespace is exptected
14525 *
14526 * Assembles an existing schema by an additional schema using
14527 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14528 * of the given @elem.
14529 *
14530 * Returns 0 if the new schema is correct, a positive error code
14531 * number otherwise and -1 in case of an internal or API error.
14532 */
14533static int
14534xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14535 xmlNodePtr elem)
14536{
14537 int ret = 0, retNs = 0;
14538 xmlAttrPtr attr;
14539
14540 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14541 if (attr != NULL) {
14542 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14543 if (retNs == -1)
14544 return (-1);
14545 }
14546 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14547 if (attr != NULL) {
14548 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14549 if (ret == -1)
14550 return (-1);
14551 }
14552 if (retNs != 0)
14553 return (retNs);
14554 else
14555 return (ret);
14556}
14557
Daniel Veillard4255d502002-04-16 15:50:10 +000014558/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014559 * xmlSchemaValidateCallback:
14560 * @ctxt: a schema validation context
14561 * @name: the name of the element detected (might be NULL)
14562 * @type: the type
14563 *
14564 * A transition has been made in the automata associated to an element
14565 * content model
14566 */
14567static void
14568xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014569 const xmlChar * name ATTRIBUTE_UNUSED,
14570 xmlSchemaTypePtr type, xmlNodePtr node)
14571{
Daniel Veillard4255d502002-04-16 15:50:10 +000014572 xmlSchemaTypePtr oldtype = ctxt->type;
14573 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014574
Daniel Veillard4255d502002-04-16 15:50:10 +000014575#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014576 xmlGenericError(xmlGenericErrorContext,
14577 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014578 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014579#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014580 /*
14581 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14582 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014583 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014584 ctxt->node = node;
14585 ctxt->cur = node->children;
14586 /*
14587 * Assemble new schemata using xsi.
14588 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014589 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014590 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014591
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014592 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14593 if (ret == -1) {
14594 xmlSchemaVCustomErr(ctxt,
14595 XML_SCHEMAV_INTERNAL,
14596 ctxt->node, NULL,
14597 "Internal error: xmlSchemaValidateElement, "
14598 "assembling schema by xsi", NULL);
14599 return;
14600 }
14601 /*
14602 * NOTE: We won't react on schema parser errors here.
14603 * TODO: But a warning would be nice.
14604 */
14605 }
14606 switch (type->type) {
14607 case XML_SCHEMA_TYPE_ELEMENT: {
14608 /*
14609 * NOTE: The build of the content model
14610 * (xmlSchemaBuildAContentModel) ensures that the element
14611 * declaration (and not a reference to it) will be given.
14612 */
14613 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14614 /*
14615 * This is paranoid coding ;-)... it should not
14616 * happen here any more.
14617 */
14618 xmlSchemaVCustomErr(ctxt,
14619 XML_SCHEMAV_INTERNAL,
14620 node, NULL,
14621 "Internal error: xmlSchemaValidateCallback, "
14622 "element declaration 'reference' encountered, "
14623 "but an element declaration was expected",
14624 NULL);
14625 return;
14626 }
14627 xmlSchemaValidateElementByDeclaration(ctxt,
14628 (xmlSchemaElementPtr) type);
14629 break;
14630 }
14631 case XML_SCHEMA_TYPE_ANY:
14632 xmlSchemaValidateElementByWildcard(ctxt, type);
14633 break;
14634 default:
14635 break;
14636 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014637 ctxt->type = oldtype;
14638 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014639}
Daniel Veillard4255d502002-04-16 15:50:10 +000014640
Daniel Veillard01fa6152004-06-29 17:04:39 +000014641/**
14642 * xmlSchemaValidateSimpleTypeValue:
14643 * @ctxt: a schema validation context
14644 * @value: the value to be validated
14645 * @fireErrors: shall errors be reported?
14646 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014647 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014648 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014649 *
14650 * Validates a value by the given type (user derived or built-in).
14651 *
14652 * Returns 0 if the value is valid, a positive error code
14653 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014654 */
14655static int
14656xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014657 xmlSchemaTypePtr type,
14658 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014659 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014660 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014661 int normalize,
14662 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014663{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014664 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014665 int ret = 0;
14666 xmlChar *normValue = NULL;
14667 int wtsp;
14668
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014669 node = ctxt->node;
14670 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014671 wtsp = ctxt->valueWS;
14672 /*
14673 * Normalize the value.
14674 */
14675 if (normalize &&
14676 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14677 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14678
14679 if ((norm != -1) && (norm > ctxt->valueWS)) {
14680 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14681 normValue = xmlSchemaCollapseString(value);
14682 else
14683 normValue = xmlSchemaWhiteSpaceReplace(value);
14684 ctxt->valueWS = norm;
14685 if (normValue != NULL)
14686 value = (const xmlChar *) normValue;
14687 }
14688 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014689 /*
14690 * The nodes of a content must be checked only once,
14691 * this is not working since list types will fire this
14692 * multiple times.
14693 */
14694 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14695 xmlNodePtr cur = ctxt->cur;
14696
14697 do {
14698 switch (cur->type) {
14699 case XML_TEXT_NODE:
14700 case XML_CDATA_SECTION_NODE:
14701 case XML_PI_NODE:
14702 case XML_COMMENT_NODE:
14703 case XML_XINCLUDE_START:
14704 case XML_XINCLUDE_END:
14705 break;
14706 case XML_ENTITY_REF_NODE:
14707 case XML_ENTITY_NODE:
14708 /* TODO: Scour the entities for illegal nodes. */
14709 TODO break;
14710 case XML_ELEMENT_NODE: {
14711 /* NOTE: Changed to an internal error, since the
14712 * existence of an element node will be already checked in
14713 * xmlSchemaValidateElementBySimpleType and in
14714 * xmlSchemaValidateElementByComplexType.
14715 */
14716 xmlSchemaVCustomErr(ctxt,
14717 XML_SCHEMAV_INTERNAL,
14718 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14719 node, type,
14720 "Element '%s' found in simple type content",
14721 cur->name);
14722 return (XML_SCHEMAV_INTERNAL);
14723 }
14724 case XML_ATTRIBUTE_NODE:
14725 case XML_DOCUMENT_NODE:
14726 case XML_DOCUMENT_TYPE_NODE:
14727 case XML_DOCUMENT_FRAG_NODE:
14728 case XML_NOTATION_NODE:
14729 case XML_HTML_DOCUMENT_NODE:
14730 case XML_DTD_NODE:
14731 case XML_ELEMENT_DECL:
14732 case XML_ATTRIBUTE_DECL:
14733 case XML_ENTITY_DECL:
14734 case XML_NAMESPACE_DECL:
14735#ifdef LIBXML_DOCB_ENABLED
14736 case XML_DOCB_DOCUMENT_NODE:
14737#endif
14738 xmlSchemaVCustomErr(ctxt,
14739 XML_SCHEMAV_INTERNAL,
14740 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14741 node, NULL,
14742 "Node of unexpected type found in simple type content",
14743 NULL);
14744 return (XML_SCHEMAV_INTERNAL);
14745 }
14746 cur = cur->next;
14747 } while (cur != NULL);
14748 }
14749
William M. Brack2f2a6632004-08-20 23:09:47 +000014750 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14751 xmlSchemaTypePtr base, anyType;
14752
14753 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14754
14755 base = type->baseType;
14756 while ((base != NULL) &&
14757 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14758 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14759 (base != anyType)) {
14760 base = base->baseType;
14761 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014762 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014763 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014764 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014765 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14766 "validating complex type '%s'\n",
14767 type->name, NULL);
14768 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14769 /*
14770 * Check facets.
14771 */
14772 /*
14773 * This is somehow not nice, since if an error occurs
14774 * the reported type will be the complex type; the spec
14775 * wants a simple type to be created on the complex type
14776 * if it has a simple content. For now we have to live with
14777 * it.
14778 */
14779 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14780 value, 0, fireErrors);
14781 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014782 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014783 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14784 "validating facets of complex type '%s'\n",
14785 type->name, NULL);
14786 } else if (ret > 0) {
14787 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014788 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014789 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014790 }
14791 }
14792 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014793
14794 if (ctxt->value != NULL) {
14795 xmlSchemaFreeValue(ctxt->value);
14796 ctxt->value = NULL;
14797 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014798 /*
14799 * STREAM-READ-CHILDREN.
14800 */
14801 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014802 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014803 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14804 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14805 else
14806 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014807 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014808 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014809 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014810 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014811 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014812 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014813 }
14814 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14815 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14816 * a literal in the ·lexical space· of {base type definition}
14817 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014818 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014819 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014820 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014821 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014822 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014823 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014824 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014825 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014826 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014827 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014828 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014829 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014830 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014831 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014832 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14833 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014834 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014835 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014836 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014837 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014838 type->name, NULL);
14839 } else if (ret > 0) {
14840 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014841 /*
14842 Disabled, since the facet validation already reports errors.
14843 if (fireErrors)
14844 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14845 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014846 }
14847 }
14848 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14849
14850 xmlSchemaTypePtr tmpType;
14851 const xmlChar *cur, *end;
14852 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014853 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014854
14855 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14856 * of white space separated tokens, each of which ·match·es a literal
14857 * in the ·lexical space· of {item type definition}
14858 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000014859
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000014860 if (value == NULL)
14861 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000014862 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014863 cur = value;
14864 do {
14865 while (IS_BLANK_CH(*cur))
14866 cur++;
14867 end = cur;
14868 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14869 end++;
14870 if (end == cur)
14871 break;
14872 tmp = xmlStrndup(cur, end - cur);
14873 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014874 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014875 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014876 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014877 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014878 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14879 "validating an item of list simple type '%s'\n",
14880 type->name, NULL);
14881 break;
14882 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014883 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014884 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014885 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014886 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014887 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014888 cur = end;
14889 } while (*cur != 0);
14890 /*
14891 * Check facets.
14892 */
14893 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014894 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014895 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014896 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014897 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014898 } else if ((ret == 0) && (applyFacets)) {
14899 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14900 value, len, fireErrors);
14901 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014902 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014903 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14904 "validating facets of list simple type '%s'\n",
14905 type->name, NULL);
14906 } else if (ret > 0) {
14907 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014908 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014909 Disabled, since the facet validation already reports errors.
14910 if (fireErrors)
14911 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014912 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014913 }
14914
Daniel Veillard01fa6152004-06-29 17:04:39 +000014915 }
14916 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14917 xmlSchemaTypeLinkPtr memberLink;
14918
14919 /*
14920 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14921 * not apply directly; however, the normalization behavior of ·union·
14922 * types is controlled by the value of whiteSpace on that one of the
14923 * ·memberTypes· against which the ·union· is successfully validated.
14924 *
14925 * This means that the value is normalized by the first validating
14926 * member type, then the facets of the union type are applied. This
14927 * needs changing of the value!
14928 */
14929
14930 /*
14931 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14932 * literal in the ·lexical space· of at least one member of
14933 * {member type definitions}
14934 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014935#ifdef DEBUG_UNION_VALIDATION
14936 printf("Union ST : '%s'\n", (const char *) type->name);
14937 printf(" fireErrors : %d\n", fireErrors);
14938 printf(" applyFacets: %d\n", applyFacets);
14939#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014940 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14941 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014942 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014943 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014944 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014945 type->name, NULL);
14946 ret = -1;
14947 }
14948 if (ret == 0) {
14949 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014950 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14951 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014952 if ((ret <= 0) || (ret == 0))
14953 break;
14954 memberLink = memberLink->next;
14955 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014956 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014957 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014958 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014959 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014960 type->name, NULL);
14961 } else if (ret > 0) {
14962 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014963 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014964 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014965 }
14966 }
14967 /*
14968 * Apply facets (pattern, enumeration).
14969 */
14970 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14971 int mws;
14972 /*
14973 * The normalization behavior of ·union· types is controlled by
14974 * the value of whiteSpace on that one of the ·memberTypes·
14975 * against which the ·union· is successfully validated.
14976 */
14977 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014978 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014979 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14980 "the value was already normalized for the union simple "
14981 "type '%s'.\n", type->name, NULL);
14982 }
14983 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14984 if (mws > ctxt->valueWS) {
14985 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14986 normValue = xmlSchemaCollapseString(value);
14987 else
14988 normValue = xmlSchemaWhiteSpaceReplace(value);
14989 if (normValue != NULL)
14990 value = (const xmlChar *) normValue;
14991 }
14992
14993 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14994 value, 0, fireErrors);
14995 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014996 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014997 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14998 "validating facets of union simple type '%s'\n",
14999 type->name, NULL);
15000 } else if (ret > 0) {
15001 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
15002 /*
15003 if (fireErrors)
15004 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15005 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015006 }
15007 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015008 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015009 ctxt->valueWS = wtsp;
15010 if (normValue != NULL)
15011 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015012 return (ret);
15013}
15014
15015/**
15016 * xmlSchemaValidateSimpleTypeElement:
15017 * @ctxt: a schema validation context
15018 * @node: the element node to be validated.
15019 *
15020 * Validate the element against a simple type.
15021 *
15022 * Returns 0 if the element is valid, a positive error code
15023 * number otherwise and -1 in case of an internal or API error.
15024 */
15025static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015026xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015027 xmlSchemaTypePtr type,
15028 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015029{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015030 xmlSchemaTypePtr oldtype;
15031 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015032 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015033 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015034 int ret = 0, retval = 0;
15035
Daniel Veillard01fa6152004-06-29 17:04:39 +000015036 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015037 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
15038 "Internal error: xmlSchemaValidateElementBySimpleType, "
15039 "bad arguments", NULL);
15040 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015041 }
15042
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015043 oldtype = ctxt->type;
15044 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015045 /*
15046 * cvc-type: 3.1.2 The element information item must have no element
15047 * information item [children].
15048 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015049 /*
15050 * STREAM: Child nodes are processed.
15051 */
15052 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015053 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015054 /*
15055 * TODO: Entities, will they produce elements as well?
15056 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015057 if (cur->type == XML_ELEMENT_NODE) {
15058 xmlSchemaVCustomErr(ctxt,
15059 XML_SCHEMAV_CVC_TYPE_3_1_2,
15060 node, type,
15061 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015062 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015063 }
15064 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015065 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015066
Daniel Veillard01fa6152004-06-29 17:04:39 +000015067 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015068 * cvc-type 3.1.1:
15069 *
15070 * The attributes of must be empty, excepting those whose namespace name
15071 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
15072 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015073 */
15074 /*
15075 * STREAM: Attribute nodes are processed.
15076 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015077 attr = node->properties;
15078 while (attr != NULL) {
15079 if ((attr->ns == NULL) ||
15080 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
15081 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
15082 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
15083 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
15084 (!xmlStrEqual
15085 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015086 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015087 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
15088 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015089 }
15090 attr = attr->next;
15091 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015092 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015093 * This will skip validation if the type is 'anySimpleType' and
15094 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015095 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015096 if ((valSimpleContent == 1) &&
15097 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
15098 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015099 xmlChar *value;
15100
15101 value = xmlNodeGetContent(node);
15102 /*
15103 * NOTE: This call will not check the content nodes, since
15104 * this should be checked here already.
15105 */
15106 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
15107 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015108 if (value != NULL)
15109 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015110 if (retval != 0)
15111 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000015112 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015113 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015114 return (ret);
15115}
Daniel Veillard4255d502002-04-16 15:50:10 +000015116
15117/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015118 * xmlSchemaValQNameAcquire:
15119 * @value: the lexical represantation of the QName value
15120 * @node: the node to search for the corresponding namespace declaration
15121 * @nsName: the resulting namespace name if found
15122 *
15123 * Checks that a value conforms to the lexical space of the type QName;
15124 * if valid, the corresponding namespace name is searched and retured
15125 * as a copy in @nsName. The local name is returned in @localName as
15126 * a copy.
15127 *
15128 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
15129 * namespace declaration was found in scope; -1 in case of an internal or
15130 * API error.
15131 */
15132static int
15133xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
15134 xmlChar **nsName, xmlChar **localName)
15135{
15136 int ret;
15137 xmlChar *local = NULL;
15138
15139 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
15140 return (-1);
15141 *nsName = NULL;
15142 *localName = NULL;
15143 ret = xmlValidateQName(value, 1);
15144 if (ret == 0) {
15145 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015146 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015147
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015148 /*
15149 * NOTE: xmlSplitQName2 will return a duplicated
15150 * string.
15151 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015152 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015153 if (local == NULL)
15154 local = xmlStrdup(value);
15155 ns = xmlSearchNs(node->doc, node, prefix);
15156 /*
15157 * A namespace need not to be found if the prefix is NULL.
15158 */
15159 if (ns != NULL) {
15160 /*
15161 * TODO: Is it necessary to duplicate the URI here?
15162 */
15163 *nsName = xmlStrdup(ns->href);
15164 } else if (prefix != NULL) {
15165 xmlFree(prefix);
15166 if (local != NULL)
15167 xmlFree(local);
15168 return (2);
15169 }
15170 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015171 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015172 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015173 } else
15174 return (1);
15175 return (ret);
15176}
15177
15178/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015179 * xmlSchemaHasElemContent:
15180 * @node: the node
15181 *
15182 * Scours the content of the given node for element
15183 * nodes.
15184 *
15185 * Returns 1 if an element node is found,
15186 * 0 otherwise.
15187 */
15188static int
15189xmlSchemaHasElemContent(xmlNodePtr node)
15190{
15191 if (node == NULL)
15192 return (0);
15193 node = node->children;
15194 while (node != NULL) {
15195 if (node->type == XML_ELEMENT_NODE)
15196 return (1);
15197 node = node->next;
15198 }
15199 return (0);
15200}
15201/**
15202 * xmlSchemaHasElemOrCharContent:
15203 * @node: the node
15204 *
15205 * Scours the content of the given node for element
15206 * and character nodes.
15207 *
15208 * Returns 1 if an element or character node is found,
15209 * 0 otherwise.
15210 */
15211static int
15212xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15213{
15214 if (node == NULL)
15215 return (0);
15216 node = node->children;
15217 while (node != NULL) {
15218 switch (node->type) {
15219 case XML_ELEMENT_NODE:
15220 /*
15221 * TODO: Ask Daniel if these are all character nodes.
15222 */
15223 case XML_TEXT_NODE:
15224 case XML_CDATA_SECTION_NODE:
15225 /*
15226 * TODO: How XML_ENTITY_NODEs evaluated?
15227 */
15228 case XML_ENTITY_REF_NODE:
15229 case XML_ENTITY_NODE:
15230 return (1);
15231 break;
15232 default:
15233 break;
15234 }
15235 node = node->next;
15236 }
15237 return (0);
15238}
15239
15240
15241/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015242 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015243 * @ctxt: a schema validation context
15244 * @node: the top node.
15245 *
15246 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015247 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015248 *
15249 * Returns 0 if the element is schemas valid, a positive error code
15250 * number otherwise and -1 in case of internal or API error.
15251 */
15252static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015253xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15254 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015255{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015256 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015257 int ret = 0;
15258 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015259 xmlAttrPtr attr;
15260 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015261 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015262
15263 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015264 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15265 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015266 * Note that @elemDecl will be the declaration and never the
15267 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015268 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015269
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015270 if (ctxt == NULL) {
15271 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15272 "Internal error: xmlSchemaValidateElementByDeclaration, "
15273 "bad arguments.\n",
15274 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015275 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015276 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015277
15278 elem = ctxt->node;
15279
15280 /*
15281 * cvc-elt (3.3.4) : 1
15282 */
15283 if (elemDecl == NULL) {
15284 xmlSchemaVCustomErr(ctxt,
15285 XML_SCHEMAV_CVC_ELT_1,
15286 elem, NULL,
15287 "No matching declaration available", NULL);
15288 return (ctxt->err);
15289 }
15290 /*
15291 * cvc-elt (3.3.4) : 2
15292 */
15293 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15294 xmlSchemaVCustomErr(ctxt,
15295 XML_SCHEMAV_CVC_ELT_2,
15296 elem, NULL,
15297 "The element declaration is abstract", NULL);
15298 return (ctxt->err);
15299 }
15300
15301 /*
15302 * cvc-elt (3.3.4) : 3
15303 * Handle 'xsi:nil'.
15304 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015305
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015306 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015307 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015308 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15309 ctxt->node = (xmlNodePtr) attr;
15310 ctxt->cur = attr->children;
15311 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15312 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15313 BAD_CAST attrValue, 1, 1, 1, 1);
15314 ctxt->node = elem;
15315 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15316 if (ret < 0) {
15317 xmlSchemaVCustomErr(ctxt,
15318 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015319 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015320 "Internal error: xmlSchemaValidateElementByDeclaration, "
15321 "validating the attribute 'xsi:nil'", NULL);
15322 if (attrValue != NULL)
15323 xmlFree(attrValue);
15324 return (-1);
15325 }
15326 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015327 /*
15328 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015329 */
15330 xmlSchemaVCustomErr(ctxt,
15331 XML_SCHEMAV_CVC_ELT_3_1,
15332 elem, NULL,
15333 "The element is not 'nillable'", NULL);
15334 } else {
15335 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015336 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015337 ret = 0;
15338 /*
15339 * cvc-elt (3.3.4) : 3.2.1
15340 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015341 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15342 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015343 xmlSchemaVCustomErr(ctxt,
15344 XML_SCHEMAV_CVC_ELT_3_2_1,
15345 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015346 elem, (xmlSchemaTypePtr) elemDecl,
15347 "The 'nilled' element must have no character or "
15348 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015349 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15350 }
15351 /*
15352 * cvc-elt (3.3.4) : 3.2.2
15353 */
15354 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15355 (elemDecl->value != NULL)) {
15356 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15357 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015358 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015359 "There is a fixed value constraint defined for "
15360 "the 'nilled' element", NULL);
15361 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15362 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015363 if (ret == 0)
15364 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015365 }
15366 }
15367 if (attrValue != NULL)
15368 xmlFree(attrValue);
15369 }
15370
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015371
15372 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015373 /*
15374 * cvc-elt (3.3.4) : 4
15375 * Handle 'xsi:type'.
15376 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015377
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015378 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15379 if (attr != NULL) {
15380 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015381
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015382 /*
15383 * TODO: We should report a *warning* that the type was overriden
15384 * by the instance.
15385 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015386
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015387 /*
15388 * cvc-elt (3.3.4) : 4.1
15389 */
15390 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15391 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15392 &nsName, &local);
15393 if (ret < 0) {
15394 xmlSchemaVCustomErr(ctxt,
15395 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015396 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015397 "Internal error: xmlSchemaValidateElementByDeclaration, "
15398 "validating the attribute 'xsi:type'", NULL);;
15399 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015400 FREE_AND_NULL(nsName)
15401 FREE_AND_NULL(local)
15402 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015403 } else if (ret == 1) {
15404 xmlSchemaVSimpleTypeErr(ctxt,
15405 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15406 (xmlNodePtr) attr, attrValue,
15407 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15408 } else if (ret == 2) {
15409 xmlSchemaVCustomErr(ctxt,
15410 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15411 (xmlNodePtr) attr,
15412 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15413 "The QName value '%s' has no "
15414 "corresponding namespace declaration in scope",
15415 attrValue);
15416 } else {
15417 /*
15418 * cvc-elt (3.3.4) : 4.2
15419 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015420 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15421 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015422 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015423
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015424 xmlSchemaVCustomErr(ctxt,
15425 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015426 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015427 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15428 "The value %s does not resolve to a type "
15429 "definition",
15430 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15431 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015432 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015433 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015434 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015435 */
15436 }
15437 }
15438 FREE_AND_NULL(attrValue)
15439 FREE_AND_NULL(nsName)
15440 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015441 }
15442 /* TODO: Change the handling of missing types according to
15443 * the spec.
15444 */
15445 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015446 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015447 XML_SCHEMAV_CVC_TYPE_1,
15448 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015449 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015450 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015451 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015452
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015453 /*
15454 * TODO: Since this should be already checked by the content model automaton,
15455 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15456 * has been changed to XML_SCHEMAV_INTERNAL.
15457 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015458 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015459 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015460 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015461 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015462 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015463 "Element %s: missing child %s\n",
15464 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015465 }
15466 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015467 }
15468 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015469 /*
15470 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015471 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015472 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015473 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015474 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015475 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015476 "Element %s: missing child %s found %s\n",
15477 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015478 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015479 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015480 */
15481 if (elemHasContent == -1)
15482 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15483 /*
15484 * cvc-elt (3.3.4) : 5
15485 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015486 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015487 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015488 * cvc-elt (3.3.4) : 5.1
15489 * If the declaration has a {value constraint},
15490 * the item has neither element nor character [children] and
15491 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015492 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015493 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15494 /*
15495 * cvc-elt (3.3.4) : 5.1.1
15496 * If the ·actual type definition· is a ·local type definition·
15497 * then the canonical lexical representation of the {value constraint}
15498 * value must be a valid default for the ·actual type definition· as
15499 * defined in Element Default Valid (Immediate) (§3.3.6).
15500 */
15501 /*
15502 * NOTE: 'local' above means types aquired by xsi:type.
15503 */
15504 ret = 0;
15505 if (actualType != elemDecl->subtypes) {
15506 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15507 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15508 elemDecl->value, NULL);
15509 if (ret < 0) {
15510 xmlSchemaVCustomErr(ctxt,
15511 XML_SCHEMAV_INTERNAL,
15512 elem, actualType,
15513 "Internal error: xmlSchemaValidateElementByDeclaration, "
15514 "validating a default value", NULL);
15515 return (-1);
15516 }
15517 }
15518 /*
15519 * cvc-elt (3.3.4) : 5.1.2
15520 * The element information item with the canonical lexical
15521 * representation of the {value constraint} value used as its
15522 * ·normalized value· must be ·valid· with respect to the
15523 * ·actual type definition· as defined by Element Locally Valid (Type)
15524 * (§3.3.4).
15525 */
15526 /*
15527 * Disable validation of the simple content, since it was already
15528 * done above.
15529 */
15530 if (ret == 0) {
15531 if (actualType != elemDecl->subtypes)
15532 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15533 else
15534 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15535 ctxt->node = elem;
15536 if (ret < 0) {
15537 xmlSchemaVCustomErr(ctxt,
15538 XML_SCHEMAV_INTERNAL,
15539 elem, actualType,
15540 "Internal error: xmlSchemaValidateElementByDeclaration, "
15541 "validating against the type", NULL);
15542 return (-1);
15543 }
15544 /*
15545 * PSVI: Create a text node on the instance element.
15546 */
15547 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15548 xmlNodePtr textChild;
15549
15550 textChild = xmlNewText(elemDecl->value);
15551 if (textChild == NULL) {
15552 xmlSchemaVCustomErr(ctxt,
15553 XML_SCHEMAV_INTERNAL,
15554 elem, actualType,
15555 "Internal error: xmlSchemaValidateElementByDeclaration, "
15556 "could not create a default text node for the instance",
15557 NULL);
15558 } else
15559 xmlAddChild(elem, textChild);
15560 }
15561 }
15562
15563 } else {
15564 /*
15565 * 5.2.1 The element information item must be ·valid· with respect
15566 * to the ·actual type definition· as defined by Element Locally
15567 * Valid (Type) (§3.3.4).
15568 */
15569 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15570 ctxt->node = elem;
15571 if (ret < 0) {
15572 xmlSchemaVCustomErr(ctxt,
15573 XML_SCHEMAV_INTERNAL,
15574 elem, actualType,
15575 "Internal error: xmlSchemaValidateElementByDeclaration, "
15576 "validating a default value", NULL);
15577 return (-1);
15578 }
15579 /*
15580 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15581 * not applied, all of the following must be true:
15582 */
15583
15584 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15585 /*
15586 * 5.2.2.1 The element information item must have no element
15587 * information item [children].
15588 *
15589 * TODO REDUNDANT: If the actual type exists, the above call to
15590 * xmlSchemaValidateElementByType will already check for element
15591 * nodes.
15592 */
15593 if (xmlSchemaHasElemContent(elem)) {
15594 xmlSchemaVCustomErr(ctxt,
15595 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15596 elem, (xmlSchemaTypePtr) elemDecl,
15597 "Elements in the content are not allowed if it is "
15598 "constrained by a fixed value", NULL);
15599 } else {
15600 /*
15601 * 5.2.2.2 The appropriate case among the following must
15602 * be true:
15603 */
15604
15605 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15606 xmlChar *value;
15607 /*
15608 * 5.2.2.2.1 If the {content type} of the ·actual type
15609 * definition· is mixed, then the *initial value* of the
15610 * item must match the canonical lexical representation
15611 * of the {value constraint} value.
15612 *
15613 * ... the *initial value* of an element information
15614 * item is the string composed of, in order, the
15615 * [character code] of each character information item in
15616 * the [children] of that element information item.
15617 */
15618 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15619 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15620 /*
15621 * TODO: Report invalid & expected values as well.
15622 * TODO: Implement the cononical stuff.
15623 */
15624 xmlSchemaVCustomErr(ctxt,
15625 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15626 elem, (xmlSchemaTypePtr) elemDecl,
15627 "The value does not match the cononical "
15628 "lexical representation of the fixed constraint",
15629 NULL);
15630 }
15631 if (value != NULL)
15632 xmlFree(value);
15633 } else if ((actualType->contentType ==
15634 XML_SCHEMA_CONTENT_SIMPLE) ||
15635 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15636 xmlChar *value;
15637
15638 /*
15639 * 5.2.2.2.2 If the {content type} of the ·actual type
15640 * definition· is a simple type definition, then the
15641 * *actual value* of the item must match the canonical
15642 * lexical representation of the {value constraint} value.
15643 */
15644 /*
15645 * TODO: *actual value* is the normalized value, impl. this.
15646 * TODO: Report invalid & expected values as well.
15647 * TODO: Implement the cononical stuff.
15648 *
15649 */
15650 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15651 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15652 xmlSchemaVCustomErr(ctxt,
15653 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15654 elem, (xmlSchemaTypePtr) elemDecl,
15655 "The normalized value does not match the cononical "
15656 "lexical representation of the fixed constraint",
15657 NULL);
15658 }
15659 if (value != NULL)
15660 xmlFree(value);
15661
15662 }
15663 /*
15664 * TODO: What if the content type is not 'mixed' or simple?
15665 */
15666
15667 }
15668
15669 }
15670 }
15671
15672 /*
15673 * TODO: 6 The element information item must be ·valid· with respect to each of
15674 * the {identity-constraint definitions} as per Identity-constraint
15675 * Satisfied (§3.11.4).
15676 */
15677
15678 /*
15679 * TODO: 7 If the element information item is the ·validation root·, it must be
15680 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15681 */
15682
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015683 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015684}
15685
Daniel Veillard4255d502002-04-16 15:50:10 +000015686/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015687 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015688 * @ctxt: a schema validation context
15689 * @node: the top node.
15690 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015691 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15692 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015693 *
15694 * Returns 0 if the element is valid, a positive error code
15695 * number otherwise and -1 in case of an internal error.
15696 */
15697static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015698xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15699 xmlSchemaWildcardPtr wild,
15700 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015701{
15702 const xmlChar *uri;
15703 int ret = 0;
15704 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015705
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015706 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015707 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15708 if (ret == -1) {
15709 xmlSchemaVCustomErr(ctxt,
15710 XML_SCHEMAV_INTERNAL,
15711 ctxt->node, NULL,
15712 "Internal error: xmlSchemaValidateElement, "
15713 "assembling schema by xsi", NULL);
15714 return (-1);
15715 }
15716 /*
15717 * NOTE: We won't react on schema parser errors here.
15718 * TODO: But a warning would be nice.
15719 */
15720 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015721 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15722 xmlSchemaElementPtr decl = NULL;
15723
15724 if (node->ns != NULL)
15725 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15726 node->name, node->ns->href, NULL);
15727 else
15728 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15729 if (decl != NULL) {
15730 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015731 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015732 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015733 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015734 "Internal error: xmlSchemaValidateAnyInternal, "
15735 "validating an element in the context of a wildcard.",
15736 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000015737 }
15738 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015739 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15740 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015741 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015742 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015743 return (ctxt->err);
15744 }
15745 }
15746 if (node->children != NULL) {
15747 child = node->children;
15748 do {
15749 if (child->type == XML_ELEMENT_NODE) {
15750 if (child->ns != NULL)
15751 uri = child->ns->href;
15752 else
15753 uri = NULL;
15754 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015755 /* TODO: error code. */
15756 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015757 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015758 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015759 return (ctxt->err);
15760 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015761 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15762 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015763 if (ret != 0)
15764 return (ret);
15765 }
15766 child = child->next;
15767 } while (child != NULL);
15768 }
15769 return (0);
15770}
15771
15772/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015773 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015774 * @ctxt: a schema validation context
15775 *
15776 * Returns 0 if the element is valid, a positive error code
15777 * number otherwise and -1 in case of an internal or API error.
15778 */
15779static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015780xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15781 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015782{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015783 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15784 (ctxt->node == NULL)) {
15785 xmlSchemaVCustomErr(ctxt,
15786 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15787 "Internal error: xmlSchemaValidateElementByWildcard, "
15788 "bad arguments", NULL);
15789 return (-1);
15790 }
15791 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15792 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015793}
15794
15795/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015796 * xmlSchemaValidateAnyTypeContent:
15797 * @ctxt: a schema validation context
15798 * @node: the current element
15799 *
15800 * This one validates the content of an element of the type
15801 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15802 * thus elements in the subtree will be validated, if a corresponding
15803 * declaration in the schema exists.
15804 *
15805 * Returns 0 if the element and its subtree is valid, a positive error code
15806 * otherwise and -1 in case of an internal or API error.
15807 */
15808static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015809xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15810 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015811{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015812 xmlSchemaTypePtr oldtype;
15813 xmlNodePtr top, cur;
15814 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015815 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015816
15817 if ((type == NULL) || (ctxt->node == NULL))
15818 return (-1);
15819
15820 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015821 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015822
15823 oldtype = ctxt->type;
15824 top = ctxt->node;
15825 /*
15826 * STREAM: Child nodes are processed.
15827 */
15828 cur = ctxt->node->children;
15829 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015830 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015831 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015832 /*
15833 * The process contents of the wildcard is "lax", thus
15834 * we need to validate the element if a declaration
15835 * exists.
15836 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015837 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015838 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015839 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015840 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015841 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015842 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015843 ctxt->node = cur;
15844 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15845 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015846 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015847 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015848 "Internal error: xmlSchemaValidateAnyTypeContent, "
15849 "validating an element in the context of a wildcard.",
15850 NULL, NULL);
15851 return (ret);
15852 } else if (ret > 0)
15853 return (ret);
15854 skipContent = 1;
15855 }
15856 }
15857 /*
15858 * Browse the full subtree, deep first.
15859 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015860 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015861 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015862 cur = cur->children;
15863 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015864 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015865 cur = cur->next;
15866 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015867 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015868 while (cur != top) {
15869 if (cur->parent != NULL)
15870 cur = cur->parent;
15871 if ((cur != top) && (cur->next != NULL)) {
15872 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015873 break;
15874 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015875 if (cur->parent == NULL) {
15876 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015877 break;
15878 }
15879 }
15880 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015881 if (cur == top)
15882 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015883 } else
15884 break;
15885 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015886 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015887 return (0);
15888}
15889
15890/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015891 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015892 * @ctxt: a schema validation context
15893 * @node: the top node.
15894 *
15895 * Validate the content of an element expected to be a complex type type
15896 * xmlschema-1.html#cvc-complex-type
15897 * Validation Rule: Element Locally Valid (Complex Type)
15898 *
15899 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015900 * number otherwise and -1 in case of internal or API error.
15901 * Note on reported errors: Although it might be nice to report
15902 * the name of the simple/complex type, used to validate the content
15903 * of a node, it is quite unnecessary: for global defined types
15904 * the local name of the element is equal to the NCName of the type,
15905 * for local defined types it makes no sense to output the internal
15906 * computed name of the type. TODO: Instead, one should attach the
15907 * struct of the type involved to the error handler - this allows
15908 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015909 */
15910static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015911xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015912 xmlSchemaTypePtr type,
15913 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015914{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015915 xmlSchemaTypePtr oldtype;
15916 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015917 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015918 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015919 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015920
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015921 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15922 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015923
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015924 oldtype = ctxt->type;
15925 ctxt->type = type;
15926 elem = ctxt->node;
15927
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015928 /*
15929 * Verify the attributes
15930 */
15931 /*
15932 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015933 */
15934 /* NOTE: removed, since a check for abstract is
15935 * done in the cvc-type constraint.
15936 *
15937 *
15938 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15939 * xmlSchemaVComplexTypeErr(ctxt,
15940 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15941 * elem, type,
15942 * "The type definition is abstract");
15943 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15944 *}
15945 */
15946
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015947 attrs = ctxt->attr;
15948 attrTop = ctxt->attrTop;
15949 /*
15950 * STREAM: Attribute nodes are processed.
15951 */
15952 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15953 xmlSchemaValidateAttributes(ctxt, elem, type);
15954 if (ctxt->attr != NULL)
15955 xmlSchemaFreeAttributeStates(ctxt->attr);
15956 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015957 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015958
15959 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015960 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015961 * model was defined. Somehow ->contModel is always not NULL
15962 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015963 * TODO: Check if the obove still occurs.
15964 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015965 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015966 case XML_SCHEMA_CONTENT_EMPTY: {
15967 /*
15968 * 1 If the {content type} is empty, then the element information
15969 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015970 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015971 /*
15972 * TODO: Is the entity stuff correct?
15973 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015974 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015975 xmlSchemaVComplexTypeErr(ctxt,
15976 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015977 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015978 "Character or element content is not allowed, "
15979 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015980 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015981 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015982 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015983 case XML_SCHEMA_CONTENT_MIXED:
15984 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015985 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015986 /*
15987 * The type has 'anyType' as its base and no content model
15988 * is defined -> use 'anyType' as the type to validate
15989 * against.
15990 */
15991 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15992 /* TODO: Handle -1. */
15993 break;
15994 }
15995 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015996 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015997 {
15998 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000015999 xmlChar *values[10];
16000 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016001
16002 /*
16003 * Content model check initialization.
16004 */
16005 if (type->contModel != NULL) {
16006 oldregexp = ctxt->regexp;
16007 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
16008 (xmlRegExecCallbacks)
16009 xmlSchemaValidateCallback, ctxt);
16010#ifdef DEBUG_AUTOMATA
16011 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
16012#endif
16013 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016014 /*
16015 * STREAM: Children are processed.
16016 */
16017 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016018 while (child != NULL) {
16019 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016020 if (child->ns != NULL)
16021 nsUri = child->ns->href;
16022 else
16023 nsUri = NULL;
16024 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016025 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016026 /*
16027 * URGENT TODO: Could we anchor an error report
16028 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016029 * TODO: Perhaps it would be better to report
16030 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016031 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016032#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000016033 if (ret < 0)
16034 xmlGenericError(xmlGenericErrorContext,
16035 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000016036 else
16037 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016038 " --> %s\n", child->name);
16039#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016040 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016041 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
16042 &values[0], &terminal);
16043 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016044 XML_SCHEMAV_ELEMENT_CONTENT,
16045 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016046 "This element is not expected",
16047 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016048 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016049 /*
16050 * Note that this will skip further validation of the
16051 * content.
16052 */
16053 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016054 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016055 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
16056 /*
16057 * TODO: Ask Daniel if this are all character nodes.
16058 */
16059 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
16060 (child->type == XML_ENTITY_NODE) ||
16061 (child->type == XML_ENTITY_REF_NODE) ||
16062 (child->type == XML_CDATA_SECTION_NODE))) {
16063 /*
16064 * 2.3 If the {content type} is element-only, then the
16065 * element information item has no character information
16066 * item [children] other than those whose [character
16067 * code] is defined as a white space in [XML 1.0 (Second
16068 * Edition)].
16069 */
William M. Brack2f2a6632004-08-20 23:09:47 +000016070 xmlSchemaVComplexTypeErr(ctxt,
16071 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016072 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016073 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016074 "because the content type is element-only");
16075 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016076 break;
16077 }
16078 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016079 }
16080 /*
16081 * Content model check finalization.
16082 */
16083 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016084 if (ret == 0) {
16085 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
16086 &values[0], &terminal);
16087 if (nbval + nbneg != 0) {
16088 /*
16089 * If a next value still exists, I does not have to
16090 * mean that there's an element missing, since it
16091 * might be an optional element. So double check it.
16092 */
16093 ret = xmlRegExecPushString(ctxt->regexp,
16094 NULL, NULL);
16095 if (ret <= 0) {
16096 ret = 1;
16097 xmlSchemaVComplexTypeElemErr(ctxt,
16098 XML_SCHEMAV_ELEMENT_CONTENT,
16099 elem, type, "Missing child element(s)",
16100 nbval, nbneg, values);
16101 } else
16102 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016103#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016104 xmlGenericError(xmlGenericErrorContext,
16105 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016106#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016107 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016108#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016109 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016110 xmlGenericError(xmlGenericErrorContext,
16111 "Element %s content check succeeded\n",
16112 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016113#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016114 }
16115 xmlRegFreeExecCtxt(ctxt->regexp);
16116 ctxt->regexp = oldregexp;
16117 }
16118 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016119 break;
16120 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016121 case XML_SCHEMA_CONTENT_BASIC:
16122 /*
16123 * If the simple content was already validated
16124 * (e.g. a default value), the content need not
16125 * to be validated again.
16126 */
16127 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016128 xmlChar *value = NULL;
16129 /*
16130 * We hit a complexType with a simpleContent resolving
16131 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000016132 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016133 /*
16134 * 2.2 If the {content type} is a simple type definition,
16135 * then the element information item has no element
16136 * information item [children], and the ·normalized value·
16137 * of the element information item is ·valid· with respect
16138 * to that simple type definition as defined by String
16139 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016140 */
16141 /*
16142 * STREAM: Children are processed.
16143 */
16144 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016145 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016146 /*
16147 * TODO: Could the entity stuff produce elements
16148 * as well?
16149 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016150 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016151 xmlSchemaVComplexTypeErr(ctxt,
16152 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016153 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016154 "Element content is not allowed, because "
16155 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016156 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16157 break;
16158 }
16159 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016160 }
16161 ctxt->node = elem;
16162 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016163 if (ret == 0) {
16164 /*
16165 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000016166 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016167 /*
16168 * STREAM: Children are processed.
16169 */
16170 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016171 value = NULL;
16172 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016173 value = xmlNodeGetContent(elem);
16174 /*
16175 * URGENT TODO: Should facets for the simple type validation be
16176 * disabled, if the derivation of facets for complex types
16177 * is implemented?
16178 */
16179 /*
16180 * NOTE: This call won't check the correct types of the
16181 * content nodes, since this should be done here.
16182 */
16183 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016184 if (ret > 0) {
16185 /*
16186 * NOTE: Although an error will be reported by
16187 * xmlSchemaValidateSimpleTypeValue, the spec wants
16188 * a specific complex type error to be reported
16189 * additionally.
16190 */
16191 xmlSchemaVComplexTypeErr(ctxt,
16192 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016193 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016194 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016195 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16196 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016197 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016198 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016199 "Element '%s': Error while validating character "
16200 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016201 elem->name, type->name);
16202 if (value != NULL)
16203 xmlFree(value);
16204 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016205 return (-1);
16206 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016207 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016208 if (ret == 0) {
16209 /*
16210 * Apply facets of the complexType. Be sure to pass the
16211 * built-in type to xmlSchemaValidateFacetsInternal.
16212 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016213 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000016214 * are used, or if the facets, defined by this complex type,
16215 * are to be used only. This here applies both facet sets.
16216 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016217
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016218 ret = xmlSchemaValidateFacetsInternal(ctxt,
16219 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016220 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016221 xmlSchemaVComplexTypeErr(ctxt,
16222 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016223 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016224 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016225 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16226 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016227 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016228 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016229 "Element '%s': Error while validating character "
16230 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000016231 "apply facets.\n",
16232 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016233 if (value != NULL)
16234 xmlFree(value);
16235 ctxt->type = oldtype;
16236 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016237 }
16238 }
16239 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016240 xmlFree(value);
16241
Daniel Veillard01fa6152004-06-29 17:04:39 +000016242 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016243 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016244 default:
16245 TODO xmlGenericError(xmlGenericErrorContext,
16246 "unimplemented content type %d\n",
16247 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016248 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016249 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016250 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016251}
16252
16253/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016254 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016255 * @ctxt: a schema validation context
16256 * @elem: an element
16257 * @type: the list of type declarations
16258 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016259 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016260 *
16261 * Returns 0 if the element is schemas valid, a positive error code
16262 * number otherwise and -1 in case of internal or API error.
16263 */
16264static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016265xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016266 xmlSchemaTypePtr type,
16267 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016268{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016269 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016270
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016271
16272 if ((ctxt == NULL) || (type == NULL)) {
16273 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16274 "Internal error: xmlSchemaValidateElementByType, "
16275 "bad arguments", NULL);
16276 return (-1);
16277 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016278 /*
16279 * This one is called by "xmlSchemaValidateElementByDeclaration".
16280 * It will forward to the proper validation
16281 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016282 */
16283 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016284 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016285 XML_SCHEMAV_CVC_TYPE_1,
16286 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016287 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016288 return (XML_SCHEMAV_CVC_TYPE_1);
16289 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016290
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016291 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016292 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016293 XML_SCHEMAV_CVC_TYPE_2,
16294 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016295 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016296 return (XML_SCHEMAV_CVC_TYPE_2);
16297 }
16298
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016299 switch (type->type) {
16300 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016301 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16302 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016303 break;
16304 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016305 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16306 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016307 break;
16308 case XML_SCHEMA_TYPE_BASIC:
16309 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16310 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16311 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016312 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16313 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016314 break;
16315 default:
16316 ret = -1;
16317 break;
16318 }
16319 if (ret == -1)
16320 return (-1);
16321 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016322 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016323}
16324
16325
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016326static int
16327xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16328 xmlSchemaAttributePtr decl,
16329 xmlSchemaAttrStatePtr state,
16330 xmlAttrPtr attr)
16331{
16332 xmlChar *value;
16333 const xmlChar *defValue;
16334 xmlSchemaValPtr defVal;
16335 int fixed;
16336 int ret;
16337
16338 if (decl->subtypes == NULL) {
16339 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16340 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16341 }
16342 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16343 ctxt->node = (xmlNodePtr) attr;
16344 ctxt->cur = attr->children;
16345 /*
16346 * NOTE: This call also checks the content nodes for correct type.
16347 */
16348 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16349 value, 1, 1, 1, 1);
16350
16351 /*
16352 * Handle 'fixed' attributes.
16353 */
16354 if (ret > 0) {
16355 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16356 /*
16357 * NOTE: Fixed value constraints will be not
16358 * applied if the value was invalid, because:
16359 * 1. The validation process does not return a precomputed
16360 * value.
16361 * 2. An invalid value implies a violation of a fixed
16362 * value constraint.
16363 */
16364 } else if (ret == 0) {
16365 state->state = XML_SCHEMAS_ATTR_CHECKED;
16366 if (xmlSchemaGetEffectiveValueConstraint(decl,
16367 &fixed, &defValue, &defVal) && (fixed == 1)) {
16368 /*
16369 * cvc-au : Attribute Locally Valid (Use)
16370 * For an attribute information item to be·valid·
16371 * with respect to an attribute use its ·normalized
16372 * value· must match the canonical lexical representation
16373 * of the attribute use's {value constraint} value, if it
16374 * is present and fixed.
16375 */
16376 /*
16377 * NOTE: the validation context holds in ctxt->value the
16378 * precomputed value of the attribute; well for some types,
16379 * fallback to string comparison if no computed value
16380 * exists.
16381 */
16382 if (((ctxt->value != NULL) &&
16383 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16384 ((ctxt->value == NULL) &&
16385 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16386 state->state =
16387 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16388 }
16389 }
16390 }
16391 if (value != NULL) {
16392 xmlFree(value);
16393 }
16394 return (ret);
16395}
16396
Daniel Veillard4255d502002-04-16 15:50:10 +000016397/**
16398 * xmlSchemaValidateAttributes:
16399 * @ctxt: a schema validation context
16400 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016401 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016402 *
16403 * Validate the attributes of an element.
16404 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016405 * 1. Existent, invalid attributes are reported in the form
16406 * "prefix:localName".
16407 * Reason: readability - it is easier to find the actual XML
16408 * representation of the attributes QName.
16409 * 2. Missing attributes are reported in the form
16410 * {"URI", "localName"}.
16411 * This is necessary, since the the prefix need not to be declared
16412 * at all, and thus is not computable.
16413 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016414 * Returns 0 if the element is schemas valid, a positive error code
16415 * number otherwise and -1 in case of internal or API error.
16416 */
16417static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016418xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016419{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016420 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016421 int ret;
16422 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016423 const xmlChar *defValue;
16424 xmlSchemaValPtr defVal;
16425 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016426 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016427 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016428 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016429 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016430 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016431 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016432#ifdef DEBUG_ATTR_VALIDATION
16433 int redundant = 0;
16434#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016435
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016436
Daniel Veillardc0826a72004-08-10 14:17:33 +000016437 /*
16438 * Allow all attributes if the type is anyType.
16439 */
16440 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16441 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016442
16443 oldnode = ctxt->node;
16444 if (type != NULL)
16445 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016446 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016447 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016448 attrDecl = attrUse->attr;
16449#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016450 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016451 printf("attr use - use: %d\n", attrDecl->occurs);
16452#endif
16453 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16454
16455 if (curState->decl == attrUse->attr) {
16456#ifdef DEBUG_ATTR_VALIDATION
16457 redundant = 1;
16458#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016459 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016460 attr = curState->attr;
16461#ifdef DEBUG_ATTR_VALIDATION
16462 printf("attr - name: %s\n", attr->name);
16463 if (attr->ns != NULL)
16464 printf("attr - ns: %s\n", attr->ns->href);
16465 else
16466 printf("attr - ns: none\n");
16467#endif
16468 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016469 if (attr == NULL)
16470 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016471 if (attrDecl->ref != NULL) {
16472 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016473 continue;
16474 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016475 if ((attrDecl->refNs == NULL) ||
16476 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016477 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016478 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016479 continue;
16480 }
16481 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016482 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016483 continue;
16484 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016485 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016486 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016487 if (attr->ns == NULL) {
16488 /*
William M. Bracke7091952004-05-11 15:09:58 +000016489 * accept an unqualified attribute only if the target
16490 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016491 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016492 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016493 /*
16494 * This check was removed, since the target namespace
16495 * was evaluated during parsing and already took
16496 * "attributeFormDefault" into account.
16497 */
16498 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016499 continue;
16500 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016501 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016502 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016503 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016504 attr->ns->href))
16505 continue;
16506 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016507 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016508#ifdef DEBUG_ATTR_VALIDATION
16509 printf("found\n");
16510#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016511 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016512 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016513 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016514 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016515 if (!found) {
16516 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16517 xmlSchemaAttrStatePtr tmp;
16518
Daniel Veillard3646d642004-06-02 19:19:14 +000016519#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016520 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016521#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016522 /*
16523 * Add a new dummy attribute state.
16524 */
16525 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16526 if (tmp == NULL) {
16527 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16528 ctxt->node = oldnode;
16529 return (-1);
16530 }
16531 tmp->attr = NULL;
16532 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16533 tmp->decl = attrDecl;
16534 tmp->next = NULL;
16535
16536 if (reqAttrStates == NULL) {
16537 reqAttrStates = tmp;
16538 reqAttrStatesTop = tmp;
16539 } else {
16540 reqAttrStatesTop->next = tmp;
16541 reqAttrStatesTop = tmp;
16542 }
16543 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16544 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16545 &fixed, &defValue, &defVal))) {
16546 xmlSchemaAttrStatePtr tmp;
16547 /*
16548 * Handle non existent default/fixed attributes.
16549 */
16550 tmp = (xmlSchemaAttrStatePtr)
16551 xmlMalloc(sizeof(xmlSchemaAttrState));
16552 if (tmp == NULL) {
16553 xmlSchemaVErrMemory(ctxt,
16554 "registering schema specified attributes", NULL);
16555 ctxt->node = oldnode;
16556 return (-1);
16557 }
16558 tmp->attr = NULL;
16559 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16560 tmp->decl = attrDecl;
16561 tmp->value = defValue;
16562 tmp->next = NULL;
16563
16564 if (defAttrStates == NULL) {
16565 defAttrStates = tmp;
16566 defAttrStates = tmp;
16567 } else {
16568 defAttrStates->next = tmp;
16569 defAttrStatesTop = tmp;
16570 }
16571 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016572 }
16573 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016574 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016575 /*
16576 * Add required attributes to the attribute states of the context.
16577 */
16578 if (reqAttrStates != NULL) {
16579 if (ctxt->attr == NULL) {
16580 ctxt->attr = reqAttrStates;
16581 } else {
16582 ctxt->attrTop->next = reqAttrStates;
16583 }
16584 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016585 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016586 /*
16587 * Process wildcards.
16588 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016589
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016590 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016591#ifdef DEBUG_ATTR_VALIDATION
16592 xmlSchemaWildcardNsPtr ns;
16593 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016594 if (type->attributeWildcard->processContents ==
16595 XML_SCHEMAS_ANY_LAX)
16596 printf("processContents: lax\n");
16597 else if (type->attributeWildcard->processContents ==
16598 XML_SCHEMAS_ANY_STRICT)
16599 printf("processContents: strict\n");
16600 else
16601 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016602 if (type->attributeWildcard->any)
16603 printf("type: any\n");
16604 else if (type->attributeWildcard->negNsSet != NULL) {
16605 printf("type: negated\n");
16606 if (type->attributeWildcard->negNsSet->value == NULL)
16607 printf("ns: (absent)\n");
16608 else
16609 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16610 } else if (type->attributeWildcard->nsSet != NULL) {
16611 printf("type: set\n");
16612 ns = type->attributeWildcard->nsSet;
16613 while (ns != NULL) {
16614 if (ns->value == NULL)
16615 printf("ns: (absent)\n");
16616 else
16617 printf("ns: %s\n", ns->value);
16618 ns = ns->next;
16619 }
16620 } else
16621 printf("empty\n");
16622
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016623
16624#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016625 curState = ctxt->attr;
16626 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016627 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16628 if (curState->attr->ns != NULL)
16629 nsURI = curState->attr->ns->href;
16630 else
16631 nsURI = NULL;
16632 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16633 nsURI)) {
16634 /*
16635 * Handle processContents.
16636 */
16637 if ((type->attributeWildcard->processContents ==
16638 XML_SCHEMAS_ANY_LAX) ||
16639 (type->attributeWildcard->processContents ==
16640 XML_SCHEMAS_ANY_STRICT)) {
16641
16642 attr = curState->attr;
16643 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016644 attr->name, nsURI);
16645 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016646 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016647 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016648 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016649 } else if (type->attributeWildcard->processContents ==
16650 XML_SCHEMAS_ANY_LAX) {
16651 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16652 }
16653 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016654 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016655 }
16656 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016657 curState = curState->next;
16658 }
16659 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016660
Daniel Veillardc0826a72004-08-10 14:17:33 +000016661 /*
16662 * Report missing and illegal attributes.
16663 */
16664 if (ctxt->attr != NULL) {
16665 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016666 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016667 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16668 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016669 if (curState->decl != NULL) {
16670 if (curState->decl->ref != NULL)
16671 attrDecl = curState->decl->refDecl;
16672 else
16673 attrDecl = curState->decl;
16674 } else
16675 attrDecl = NULL;
16676 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16677 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16678 } else if (curState->state ==
16679 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16680 xmlSchemaVCustomErr(ctxt,
16681 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16682 (xmlNodePtr) attr,
16683 (xmlSchemaTypePtr) attrDecl,
16684 "The type definition is absent",
16685 NULL);
16686 } else if (curState->state ==
16687 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16688 xmlSchemaVCustomErr(ctxt,
16689 XML_SCHEMAV_CVC_AU,
16690 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16691 "The value does not match the fixed value "
16692 "constraint", NULL);
16693 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016694 /* TODO: "prohibited" won't ever be touched here!.
16695 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16696 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016697 /*
16698 * TODO: One might report different error messages
16699 * for the following errors.
16700 */
16701 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016702 xmlSchemaVIllegalAttrErr(ctxt,
16703 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16704 } else {
16705 xmlSchemaVIllegalAttrErr(ctxt,
16706 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16707 }
16708 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016709 }
16710 curState = curState->next;
16711 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016712 }
16713
16714 /*
16715 * Add missing default/fixed attributes.
16716 */
16717 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16718 curState = defAttrStates;
16719 while (curState != NULL) {
16720 attrDecl = curState->decl;
16721 if (attrDecl->ref != NULL)
16722 attrDecl = attrDecl->refDecl;
16723 /*
16724 * PSVI: Add a new attribute node to the current element.
16725 */
16726 if (attrDecl->targetNamespace == NULL) {
16727 xmlNewProp(elem, attrDecl->name, curState->value);
16728 } else {
16729 xmlNsPtr ns;
16730
16731 ns = xmlSearchNsByHref(elem->doc, elem,
16732 attrDecl->targetNamespace);
16733 if (ns == NULL) {
16734 xmlChar prefix[12];
16735 int counter = 1;
16736
16737 attr = curState->attr;
16738 /*
16739 * Create a namespace declaration on the validation
16740 * root node if no namespace declaration is in scope.
16741 */
16742 snprintf((char *) prefix, sizeof(prefix), "p");
16743 /*
16744 * This is somehow not performant, since the ancestor
16745 * axis beyond @elem will be searched as well.
16746 */
16747 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16748 while (ns != NULL) {
16749 if (counter > 1000) {
16750 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16751 XML_SCHEMAV_INTERNAL,
16752 "Internal error: xmlSchemaValidateAttributes, "
16753 "could not compute a ns prefix for "
16754 "default/fixed attribute '%s'.\n",
16755 attrDecl->name, NULL);
16756
16757 break;
16758 }
16759 snprintf((char *) prefix,
16760 sizeof(prefix), "p%d", counter++);
16761 ns = xmlSearchNs(elem->doc, elem,
16762 BAD_CAST prefix);
16763 }
16764 if (ns == NULL) {
16765 ns = xmlNewNs(ctxt->validationRoot,
16766 attrDecl->targetNamespace, BAD_CAST prefix);
16767 xmlNewNsProp(elem, ns, attrDecl->name,
16768 curState->value);
16769 }
16770 } else {
16771 xmlNewNsProp(elem, ns, attrDecl->name,
16772 curState->value);
16773 }
16774 }
16775 curState = curState->next;
16776 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016777 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016778 if (defAttrStates != NULL)
16779 xmlSchemaFreeAttributeStates(defAttrStates);
16780
Daniel Veillard3646d642004-06-02 19:19:14 +000016781#ifdef DEBUG_ATTR_VALIDATION
16782 if (redundant)
16783 xmlGenericError(xmlGenericErrorContext,
16784 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16785 type->name);
16786#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016787 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016788 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016789}
16790
16791/**
16792 * xmlSchemaValidateElement:
16793 * @ctxt: a schema validation context
16794 * @elem: an element
16795 *
16796 * Validate an element in a tree
16797 *
16798 * Returns 0 if the element is schemas valid, a positive error code
16799 * number otherwise and -1 in case of internal or API error.
16800 */
16801static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016802xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016803{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016804 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016805 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016806
Daniel Veillardc0826a72004-08-10 14:17:33 +000016807 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016808 * This one is called by xmlSchemaValidateDocument and
16809 * xmlSchemaValidateOneElement.
16810 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016811 if (ctxt->schema == NULL) {
16812 /*
16813 * No schema was specified at time of creation of the validation
16814 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16815 * of the instance to build a schema.
16816 */
16817 if (ctxt->pctxt == NULL)
16818 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16819 if (ctxt->pctxt == NULL)
16820 return (-1);
16821 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16822 if (ctxt->schema == NULL)
16823 return (-1);
16824 /* TODO: assign user data. */
16825 ctxt->pctxt->error = ctxt->error;
16826 ctxt->pctxt->warning = ctxt->warning;
16827 ctxt->xsiAssemble = 1;
16828 } else
16829 ctxt->xsiAssemble = 0;
16830 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16831 * ctxt->xsiAssemble = 1;
16832 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016833 /*
16834 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016835 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016836 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016837 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16838 if (ret == -1) {
16839 xmlSchemaVCustomErr(ctxt,
16840 XML_SCHEMAV_INTERNAL,
16841 ctxt->node, NULL,
16842 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016843 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016844 }
16845 /*
16846 * NOTE: We won't react on schema parser errors here.
16847 * TODO: But a warning would be nice.
16848 */
16849 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016850 if (ret != -1) {
16851 if (ctxt->node->ns != NULL)
16852 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16853 ctxt->node->ns->href);
16854 else
16855 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16856
16857 if (elemDecl == NULL) {
16858 xmlSchemaVCustomErr(ctxt,
16859 XML_SCHEMAV_CVC_ELT_1,
16860 ctxt->node, NULL,
16861 "No matching global declaration available", NULL);
16862 ret = XML_SCHEMAV_CVC_ELT_1;
16863 } else {
16864 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16865 if (ret < 0) {
16866 xmlSchemaVCustomErr(ctxt,
16867 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16868 "Internal error: xmlSchemaValidateElement, "
16869 "calling validation by declaration", NULL);
16870 }
16871 }
16872 }
16873 /* ctxt->xsiAssemble = 0; */
16874 if (ctxt->xsiAssemble) {
16875 if (ctxt->schema != NULL) {
16876 xmlSchemaFree(ctxt->schema);
16877 ctxt->schema = NULL;
16878 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016880 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016881}
16882
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016883
Daniel Veillard4255d502002-04-16 15:50:10 +000016884/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016885 * xmlSchemaValidateOneElement:
16886 * @ctxt: a schema validation context
16887 * @elem: an element node
16888 *
16889 * Validate a branch of a tree, starting with the given @elem.
16890 *
16891 * Returns 0 if the element and its subtree is valid, a positive error
16892 * code number otherwise and -1 in case of an internal or API error.
16893 */
16894int
16895xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16896{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016897 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016898 return (-1);
16899
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016900 if (ctxt->schema == NULL) {
16901 xmlSchemaVErr(ctxt, NULL,
16902 XML_SCHEMAV_INTERNAL,
16903 "API error: xmlSchemaValidateOneElement, "
16904 "no schema specified.\n", NULL, NULL);
16905 return (-1);
16906 }
16907
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016908 ctxt->doc = elem->doc;
16909 ctxt->err = 0;
16910 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016911 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016912 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016913 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016914}
16915
16916/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016917 * xmlSchemaValidateDocument:
16918 * @ctxt: a schema validation context
16919 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016920 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016921 *
16922 * Validate a document tree in memory.
16923 *
16924 * Returns 0 if the document is schemas valid, a positive error code
16925 * number otherwise and -1 in case of internal or API error.
16926 */
16927static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016928xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16929{
Daniel Veillard4255d502002-04-16 15:50:10 +000016930 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016931
Daniel Veillard4255d502002-04-16 15:50:10 +000016932 root = xmlDocGetRootElement(doc);
16933 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016934 xmlSchemaVCustomErr(ctxt,
16935 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16936 (xmlNodePtr) doc, NULL,
16937 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016938 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016939 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016940 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016941 /*
16942 * Okay, start the recursive validation
16943 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016944 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016945 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016946 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016947
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016948 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016949}
16950
16951/************************************************************************
16952 * *
16953 * SAX Validation code *
16954 * *
16955 ************************************************************************/
16956
16957/************************************************************************
16958 * *
16959 * Validation interfaces *
16960 * *
16961 ************************************************************************/
16962
16963/**
16964 * xmlSchemaNewValidCtxt:
16965 * @schema: a precompiled XML Schemas
16966 *
16967 * Create an XML Schemas validation context based on the given schema
16968 *
16969 * Returns the validation context or NULL in case of error
16970 */
16971xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016972xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16973{
Daniel Veillard4255d502002-04-16 15:50:10 +000016974 xmlSchemaValidCtxtPtr ret;
16975
16976 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16977 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016978 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016979 return (NULL);
16980 }
16981 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016982 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016983 ret->attrTop = NULL;
16984 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016985 return (ret);
16986}
16987
16988/**
16989 * xmlSchemaFreeValidCtxt:
16990 * @ctxt: the schema validation context
16991 *
16992 * Free the resources associated to the schema validation context
16993 */
16994void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016995xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16996{
Daniel Veillard4255d502002-04-16 15:50:10 +000016997 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016998 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016999 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017000 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000017001 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017002 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017003 if (ctxt->pctxt != NULL) {
17004 xmlSchemaFreeParserCtxt(ctxt->pctxt);
17005 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017006 xmlFree(ctxt);
17007}
17008
17009/**
17010 * xmlSchemaSetValidErrors:
17011 * @ctxt: a schema validation context
17012 * @err: the error function
17013 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000017014 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000017015 *
William M. Brack2f2a6632004-08-20 23:09:47 +000017016 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000017017 */
17018void
17019xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017020 xmlSchemaValidityErrorFunc err,
17021 xmlSchemaValidityWarningFunc warn, void *ctx)
17022{
Daniel Veillard4255d502002-04-16 15:50:10 +000017023 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017024 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017025 ctxt->error = err;
17026 ctxt->warning = warn;
17027 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017028 if (ctxt->pctxt != NULL)
17029 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000017030}
17031
17032/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017033 * xmlSchemaGetValidErrors:
17034 * @ctxt: a XML-Schema validation context
17035 * @err: the error function result
17036 * @warn: the warning function result
17037 * @ctx: the functions context result
17038 *
17039 * Get the error and warning callback informations
17040 *
17041 * Returns -1 in case of error and 0 otherwise
17042 */
17043int
17044xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
17045 xmlSchemaValidityErrorFunc * err,
17046 xmlSchemaValidityWarningFunc * warn, void **ctx)
17047{
17048 if (ctxt == NULL)
17049 return (-1);
17050 if (err != NULL)
17051 *err = ctxt->error;
17052 if (warn != NULL)
17053 *warn = ctxt->warning;
17054 if (ctx != NULL)
17055 *ctx = ctxt->userData;
17056 return (0);
17057}
17058
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017059
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017060/**
Daniel Veillard6927b102004-10-27 17:29:04 +000017061 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017062 * @ctxt: a schema validation context
17063 * @options: a combination of xmlSchemaValidOption
17064 *
17065 * Sets the options to be used during the validation.
17066 *
17067 * Returns 0 in case of success, -1 in case of an
17068 * API error.
17069 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017070int
17071xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
17072 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017073
17074{
17075 int i;
17076
17077 if (ctxt == NULL)
17078 return (-1);
17079 /*
17080 * WARNING: Change the start value if adding to the
17081 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017082 * TODO: Is there an other, more easy to maintain,
17083 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017084 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017085 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017086 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017087 xmlSchemaVErr(ctxt, NULL,
17088 XML_SCHEMAV_INTERNAL,
17089 "Internal error: xmlSchemaSetValidOptions, "
17090 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017091 return (-1);
17092 }
17093 }
17094 ctxt->options = options;
17095 return (0);
17096}
17097
17098/**
Daniel Veillard6927b102004-10-27 17:29:04 +000017099 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017100 * @ctxt: a schema validation context
17101 *
William M. Brack21e4ef22005-01-02 09:53:13 +000017102 * Get the validation context options.
17103 *
17104 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017105 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017106int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017107xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
17108
17109{
17110 if (ctxt == NULL)
17111 return (-1);
17112 else
17113 return (ctxt->options);
17114}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017115
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017116
Daniel Veillard259f0df2004-08-18 09:13:18 +000017117/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017118 * xmlSchemaValidateDoc:
17119 * @ctxt: a schema validation context
17120 * @doc: a parsed document tree
17121 *
17122 * Validate a document tree in memory.
17123 *
17124 * Returns 0 if the document is schemas valid, a positive error code
17125 * number otherwise and -1 in case of internal or API error.
17126 */
17127int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017128xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
17129{
Daniel Veillard4255d502002-04-16 15:50:10 +000017130 int ret;
17131
17132 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017133 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017134
17135 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000017136 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017137 ctxt->nberrors = 0;
17138
17139 /*
17140 if (ctxt->schema == NULL) {
17141 xmlSchemaVErr(ctxt, NULL,
17142 XML_SCHEMAV_INTERNAL,
17143 "API error: xmlSchemaValidateDoc, "
17144 "no schema specified and assembling of schemata "
17145 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
17146 "is not enabled.\n", NULL, NULL);
17147 return (-1);
17148 }
17149 */
Daniel Veillard4255d502002-04-16 15:50:10 +000017150 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017151 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000017152}
17153
17154/**
17155 * xmlSchemaValidateStream:
17156 * @ctxt: a schema validation context
17157 * @input: the input to use for reading the data
17158 * @enc: an optional encoding information
17159 * @sax: a SAX handler for the resulting events
17160 * @user_data: the context to provide to the SAX handler.
17161 *
17162 * Validate a document tree in memory.
17163 *
17164 * Returns 0 if the document is schemas valid, a positive error code
17165 * number otherwise and -1 in case of internal or API error.
17166 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017167int
Daniel Veillard4255d502002-04-16 15:50:10 +000017168xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017169 xmlParserInputBufferPtr input, xmlCharEncoding enc,
17170 xmlSAXHandlerPtr sax, void *user_data)
17171{
Daniel Veillard4255d502002-04-16 15:50:10 +000017172 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017173 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017174 ctxt->input = input;
17175 ctxt->enc = enc;
17176 ctxt->sax = sax;
17177 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017178 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017179}
17180
17181#endif /* LIBXML_SCHEMAS_ENABLED */