blob: d2ddc5918e4aaf1abb1837b1d1d7cea6220ff908 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000037
Daniel Veillarda84c0b32003-06-02 16:58:46 +000038/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000039
Daniel Veillard82bbbd42003-05-11 20:16:09 +000040/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000041
Daniel Veillard82bbbd42003-05-11 20:16:09 +000042/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000043
Daniel Veillard118aed72002-09-24 14:13:13 +000044/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000045
Daniel Veillard4255d502002-04-16 15:50:10 +000046/* #define DEBUG_AUTOMATA 1 */
47
Daniel Veillard3646d642004-06-02 19:19:14 +000048/* #define DEBUG_ATTR_VALIDATION 1 */
49
Daniel Veillardc0826a72004-08-10 14:17:33 +000050/* #define DEBUG_UNION_VALIDATION 1 */
51
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define UNBOUNDED (1 << 30)
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
William M. Brack2f2a6632004-08-20 23:09:47 +000059#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000060
Daniel Veillard4255d502002-04-16 15:50:10 +000061/*
62 * The XML Schemas namespaces
63 */
64static const xmlChar *xmlSchemaNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema";
66
67static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
68 "http://www.w3.org/2001/XMLSchema-instance";
69
Daniel Veillardc0826a72004-08-10 14:17:33 +000070static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
71 "Element decl.";
72static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
73 "Element ref.";
74static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
75 "Attribute decl.";
76static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
77 "Attribute ref.";
78static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
79 "ST";
80static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
81 "CT";
82
Daniel Veillard4255d502002-04-16 15:50:10 +000083#define IS_SCHEMA(node, type) \
84 ((node != NULL) && (node->ns != NULL) && \
85 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
86 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
87
Daniel Veillardc0826a72004-08-10 14:17:33 +000088#define FREE_AND_NULL(str) \
89 if (str != NULL) { \
90 xmlFree(str); \
91 str = NULL; \
92 }
93
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000094#define IS_ANYTYPE(item) \
95 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
96 (item->builtInType == XML_SCHEMAS_ANYTYPE))
97
98#define IS_COMPLEX_TYPE(item) \
99 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
100 (item->builtInType == XML_SCHEMAS_ANYTYPE))
101
102#define IS_SIMPLE_TYPE(item) \
103 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
104 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
105 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
106
Daniel Veillardc0826a72004-08-10 14:17:33 +0000107#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
108#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
109#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define XML_SCHEMAS_PARSE_ERROR 1
112
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000113#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000115
116/*
117* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
118* allow to assemble schemata with
119* the same target namespace from
120* different sources; otherwise, the first
121* encountered schema with a specific target
122* namespace will be used only *
123
124*
125* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
126* locate schemata to be imported
127* using the namespace name; otherwise
128* the location URI will be used */
129
130/*
131* xmlSchemaParserOption:
132*
133* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000135typedef enum {
136 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000137 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000138 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000139 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000140} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000141*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000142
143/*
144XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000145 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
146 int options);
147XMLPUBFUN int XMLCALL
148 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
149
150*/
151
152typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
153typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
154struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000155 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156 int nbItems; /* used for dynamic addition of schemata */
157 int sizeItems; /* used for dynamic addition of schemata */
158};
159
Daniel Veillard4255d502002-04-16 15:50:10 +0000160struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000161 void *userData; /* user specific data block */
162 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
163 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000164 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000165 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000166 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000167
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000168 xmlSchemaPtr topschema; /* The main schema */
169 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
170
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000171 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000172 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000173 int counter;
174
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000175 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000177 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000178
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179 const char *buffer;
180 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000181
Daniel Veillard4255d502002-04-16 15:50:10 +0000182 /*
183 * Used to build complex element content models
184 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000185 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 xmlAutomataStatePtr start;
187 xmlAutomataStatePtr end;
188 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000189
190 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000191 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000192 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
193 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194 xmlSchemaAssemblePtr assemble;
195 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000196 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000197};
198
199
200#define XML_SCHEMAS_ATTR_UNKNOWN 1
201#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000202#define XML_SCHEMAS_ATTR_PROHIBITED 3
203#define XML_SCHEMAS_ATTR_MISSING 4
204#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
205#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000206#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
207#define XML_SCHEMAS_ATTR_DEFAULT 8
Daniel Veillard4255d502002-04-16 15:50:10 +0000208
209typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
210typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
211struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000212 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000213 xmlAttrPtr attr;
214 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000215 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000216 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000217};
218
219/**
220 * xmlSchemaValidCtxt:
221 *
222 * A Schemas validation context
223 */
224
225struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *userData; /* user specific data block */
227 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
228 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000229 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000230
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000231 xmlSchemaPtr schema; /* The schema in use */
232 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlCharEncoding enc;
235 xmlSAXHandlerPtr sax;
236 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 xmlDocPtr myDoc;
239 int err;
240 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000241
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000242 xmlNodePtr node;
243 xmlNodePtr cur;
244 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000246 xmlRegExecCtxtPtr regexp;
247 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248
Daniel Veillard3646d642004-06-02 19:19:14 +0000249 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000250 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000251 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000252 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlNodePtr validationRoot;
255 xmlSchemaParserCtxtPtr pctxt;
256 int xsiAssemble;
Daniel Veillard4255d502002-04-16 15:50:10 +0000257};
258
Daniel Veillard1d913862003-11-21 00:28:39 +0000259/*
260 * These are the entries in the schemas importSchemas hash table
261 */
262typedef struct _xmlSchemaImport xmlSchemaImport;
263typedef xmlSchemaImport *xmlSchemaImportPtr;
264struct _xmlSchemaImport {
265 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000266 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000267 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000268 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000269};
Daniel Veillard4255d502002-04-16 15:50:10 +0000270
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000271/*
272 * These are the entries associated to includes in a schemas
273 */
274typedef struct _xmlSchemaInclude xmlSchemaInclude;
275typedef xmlSchemaInclude *xmlSchemaIncludePtr;
276struct _xmlSchemaInclude {
277 xmlSchemaIncludePtr next;
278
279 const xmlChar *schemaLocation;
280 xmlDocPtr doc;
281};
282
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000283typedef struct _xmlSchemaParticle xmlSchemaParticle;
284typedef xmlSchemaParticle *xmlSchemaParticlePtr;
285struct _xmlSchemaParticle {
286 xmlSchemaTypeType type;
287 xmlSchemaParticlePtr next; /* the next particle if in a list */
288 int minOccurs;
289 int maxOccurs;
290 xmlSchemaTypePtr term;
291};
292
293
294typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
295typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
296struct _xmlSchemaModelGroup {
297 xmlSchemaTypeType type;
298 int compositor; /* one of all, choice or sequence */
299 xmlSchemaParticlePtr particles; /* list of particles */
300 xmlSchemaAnnotPtr annot;
301};
302
303typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
304typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
305struct _xmlSchemaModelGroupDef {
306 xmlSchemaTypeType type;
307 const xmlChar *name;
308 const xmlChar *targetNamespace;
309 xmlSchemaModelGroupPtr modelGroup;
310 xmlSchemaAnnotPtr annot;
311};
312
Daniel Veillard4255d502002-04-16 15:50:10 +0000313/************************************************************************
314 * *
315 * Some predeclarations *
316 * *
317 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000319static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
320 xmlSchemaPtr schema,
321 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000322static void
323xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
324 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
325static const char *
326xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
327static int
328xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000329 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000330 const xmlChar *value,
331 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000332 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000333 int normalize,
334 int checkNodes);
335static int
336xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
337 xmlSchemaElementPtr elemDecl);
338static int
339xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
340 xmlSchemaTypePtr type);
341static int
342xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000343static int
344xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
345 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000346
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000347/************************************************************************
348 * *
349 * Datatype error handlers *
350 * *
351 ************************************************************************/
352
353/**
354 * xmlSchemaPErrMemory:
355 * @node: a context node
356 * @extra: extra informations
357 *
358 * Handle an out of memory condition
359 */
360static void
361xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
362 const char *extra, xmlNodePtr node)
363{
364 if (ctxt != NULL)
365 ctxt->nberrors++;
366 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
367 extra);
368}
369
370/**
371 * xmlSchemaPErr:
372 * @ctxt: the parsing context
373 * @node: the context node
374 * @error: the error code
375 * @msg: the error message
376 * @str1: extra data
377 * @str2: extra data
378 *
379 * Handle a parser error
380 */
381static void
382xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
383 const char *msg, const xmlChar * str1, const xmlChar * str2)
384{
385 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000386 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000387 void *data = NULL;
388
389 if (ctxt != NULL) {
390 ctxt->nberrors++;
391 channel = ctxt->error;
392 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000393 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000394 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000395 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000396 error, XML_ERR_ERROR, NULL, 0,
397 (const char *) str1, (const char *) str2, NULL, 0, 0,
398 msg, str1, str2);
399}
400
401/**
402 * xmlSchemaPErr2:
403 * @ctxt: the parsing context
404 * @node: the context node
405 * @node: the current child
406 * @error: the error code
407 * @msg: the error message
408 * @str1: extra data
409 * @str2: extra data
410 *
411 * Handle a parser error
412 */
413static void
414xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
415 xmlNodePtr child, int error,
416 const char *msg, const xmlChar * str1, const xmlChar * str2)
417{
418 if (child != NULL)
419 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
420 else
421 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
422}
423
Daniel Veillard01fa6152004-06-29 17:04:39 +0000424
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000425/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000426 * xmlSchemaPErrExt:
427 * @ctxt: the parsing context
428 * @node: the context node
429 * @error: the error code
430 * @strData1: extra data
431 * @strData2: extra data
432 * @strData3: extra data
433 * @msg: the message
434 * @str1: extra parameter for the message display
435 * @str2: extra parameter for the message display
436 * @str3: extra parameter for the message display
437 * @str4: extra parameter for the message display
438 * @str5: extra parameter for the message display
439 *
440 * Handle a parser error
441 */
442static void
443xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
444 const xmlChar * strData1, const xmlChar * strData2,
445 const xmlChar * strData3, const char *msg, const xmlChar * str1,
446 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
447 const xmlChar * str5)
448{
449
450 xmlGenericErrorFunc channel = NULL;
451 xmlStructuredErrorFunc schannel = NULL;
452 void *data = NULL;
453
454 if (ctxt != NULL) {
455 ctxt->nberrors++;
456 channel = ctxt->error;
457 data = ctxt->userData;
458 schannel = ctxt->serror;
459 }
460 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
461 error, XML_ERR_ERROR, NULL, 0,
462 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000463 (const char *) strData3, 0, 0, msg, str1, str2,
464 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000465}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000466
Daniel Veillard3646d642004-06-02 19:19:14 +0000467
468/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000469 * xmlSchemaVTypeErrMemory:
470 * @node: a context node
471 * @extra: extra informations
472 *
473 * Handle an out of memory condition
474 */
475static void
476xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
477 const char *extra, xmlNodePtr node)
478{
479 if (ctxt != NULL) {
480 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000481 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000482 }
483 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
484 extra);
485}
486
487/**
488 * xmlSchemaVErr3:
489 * @ctxt: the validation context
490 * @node: the context node
491 * @error: the error code
492 * @msg: the error message
493 * @str1: extra data
494 * @str2: extra data
495 * @str3: extra data
496 *
497 * Handle a validation error
498 */
499static void
500xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
501 const char *msg, const xmlChar *str1, const xmlChar *str2,
502 const xmlChar *str3)
503{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000504 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000505 xmlGenericErrorFunc channel = NULL;
506 void *data = NULL;
507
508 if (ctxt != NULL) {
509 ctxt->nberrors++;
510 ctxt->err = error;
511 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000512 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000513 data = ctxt->userData;
514 }
515 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000516 /* Removed, since the old schema error codes have been
517 * substituted for the global error codes.
518 *
519 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
520 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000521 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000522 error, XML_ERR_ERROR, NULL, 0,
523 (const char *) str1, (const char *) str2,
524 (const char *) str3, 0, 0,
525 msg, str1, str2, str3);
526}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000527
528/**
529 * xmlSchemaVErrExt:
530 * @ctxt: the validation context
531 * @node: the context node
532 * @error: the error code
533 * @msg: the message
534 * @str1: extra parameter for the message display
535 * @str2: extra parameter for the message display
536 * @str3: extra parameter for the message display
537 * @str4: extra parameter for the message display
538 * @str5: extra parameter for the message display
539 *
540 * Handle a validation error
541 */
542static void
543xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
544 const char *msg, const xmlChar * str1,
545 const xmlChar * str2, const xmlChar * str3,
546 const xmlChar * str4, const xmlChar * str5)
547{
548 xmlStructuredErrorFunc schannel = NULL;
549 xmlGenericErrorFunc channel = NULL;
550 void *data = NULL;
551
552 if (ctxt != NULL) {
553 ctxt->nberrors++;
554 ctxt->err = error;
555 channel = ctxt->error;
556 schannel = ctxt->serror;
557 data = ctxt->userData;
558 }
559 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000560 /* Removed, since the old schema error codes have been
561 * substituted for the global error codes.
562 *
563 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
564 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000565 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
566 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
567 msg, str1, str2, str3, str4, str5);
568}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000569/**
570 * xmlSchemaVErr:
571 * @ctxt: the validation context
572 * @node: the context node
573 * @error: the error code
574 * @msg: the error message
575 * @str1: extra data
576 * @str2: extra data
577 *
578 * Handle a validation error
579 */
580static void
581xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
582 const char *msg, const xmlChar * str1, const xmlChar * str2)
583{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000584 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000585 xmlGenericErrorFunc channel = NULL;
586 void *data = NULL;
587
588 if (ctxt != NULL) {
589 ctxt->nberrors++;
590 ctxt->err = error;
591 channel = ctxt->error;
592 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000593 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000594 }
595 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000596 /* Removed, since the old schema error codes have been
597 * substituted for the global error codes.
598 *
599 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
600 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000601 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000602 error, XML_ERR_ERROR, NULL, 0,
603 (const char *) str1, (const char *) str2, NULL, 0, 0,
604 msg, str1, str2);
605}
Daniel Veillard4255d502002-04-16 15:50:10 +0000606
Daniel Veillardc0826a72004-08-10 14:17:33 +0000607/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000608 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000609 * @attr: the attribute declaration/use
610 *
611 * Returns the name of the attribute; if the attribute
612 * is a reference, the name of the referenced global type will be returned.
613 */
614static const xmlChar *
615xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
616{
617 if (attr->ref != NULL)
618 return(attr->ref);
619 else
620 return(attr->name);
621}
622
623/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000624 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000625 * @type: the type (element or attribute)
626 *
627 * Returns the target namespace URI of the type; if the type is a reference,
628 * the target namespace of the referenced type will be returned.
629 */
630static const xmlChar *
631xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
632{
633 if (attr->ref != NULL)
634 return (attr->refNs);
635 else
636 return(attr->targetNamespace);
637}
638
639/**
640 * xmlSchemaFormatNsUriLocal:
641 * @buf: the string buffer
642 * @uri: the namespace URI
643 * @local: the local name
644 *
645 * Returns a representation of the given URI used
646 * for error reports.
647 *
648 * Returns an empty string, if @ns is NULL, a formatted
649 * string otherwise.
650 */
651static const xmlChar*
652xmlSchemaFormatNsUriLocal(xmlChar **buf,
653 const xmlChar *uri, const xmlChar *local)
654{
655 if (*buf != NULL)
656 xmlFree(*buf);
657 if (uri == NULL) {
658 *buf = xmlStrdup(BAD_CAST "{'");
659 *buf = xmlStrcat(*buf, local);
660 } else {
661 *buf = xmlStrdup(BAD_CAST "{'");
662 *buf = xmlStrcat(*buf, uri);
663 *buf = xmlStrcat(*buf, BAD_CAST "', '");
664 *buf = xmlStrcat(*buf, local);
665 }
666 *buf = xmlStrcat(*buf, BAD_CAST "'}");
667 return ((const xmlChar *) *buf);
668}
669
670/**
671 * xmlSchemaFormatNsPrefixLocal:
672 * @buf: the string buffer
673 * @ns: the namespace
674 * @local: the local name
675 *
676 * Returns a representation of the given URI used
677 * for error reports.
678 *
679 * Returns an empty string, if @ns is NULL, a formatted
680 * string otherwise.
681 */
682static const xmlChar*
683xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
684 xmlNsPtr ns, const xmlChar *local)
685{
686 if (*buf != NULL) {
687 xmlFree(*buf);
688 *buf = NULL;
689 }
690 if ((ns == NULL) || (ns->prefix == NULL))
691 return(local);
692 else {
693 *buf = xmlStrdup(ns->prefix);
694 *buf = xmlStrcat(*buf, BAD_CAST ":");
695 *buf = xmlStrcat(*buf, local);
696 }
697 return ((const xmlChar *) *buf);
698}
699
700/**
701 * xmlSchemaFormatItemForReport:
702 * @buf: the string buffer
703 * @itemDes: the designation of the item
704 * @itemName: the name of the item
705 * @item: the item as an object
706 * @itemNode: the node of the item
707 * @local: the local name
708 * @parsing: if the function is used during the parse
709 *
710 * Returns a representation of the given item used
711 * for error reports.
712 *
713 * The following order is used to build the resulting
714 * designation if the arguments are not NULL:
715 * 1a. If itemDes not NULL -> itemDes
716 * 1b. If (itemDes not NULL) and (itemName not NULL)
717 * -> itemDes + itemName
718 * 2. If the preceding was NULL and (item not NULL) -> item
719 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
720 *
721 * If the itemNode is an attribute node, the name of the attribute
722 * will be appended to the result.
723 *
724 * Returns the formatted string and sets @buf to the resulting value.
725 */
726static xmlChar*
727xmlSchemaFormatItemForReport(xmlChar **buf,
728 const xmlChar *itemDes,
729 xmlSchemaTypePtr item,
730 xmlNodePtr itemNode,
731 int parsing)
732{
733 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000734 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000735
736 if (*buf != NULL) {
737 xmlFree(*buf);
738 *buf = NULL;
739 }
740
William M. Brack2f2a6632004-08-20 23:09:47 +0000741 if (itemDes != NULL) {
742 *buf = xmlStrdup(itemDes);
743 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000744 if (item->type == XML_SCHEMA_TYPE_BASIC) {
745 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
746 *buf = xmlStrdup(BAD_CAST "'anyType'");
747 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
748 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
749 else {
750 /* *buf = xmlStrdup(BAD_CAST "bi "); */
751 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
752 *buf = xmlStrdup(BAD_CAST "'");
753 *buf = xmlStrcat(*buf, item->name);
754 *buf = xmlStrcat(*buf, BAD_CAST "'");
755 }
756 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
757 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
758 *buf = xmlStrdup(xmlSchemaElemDesST);
759 *buf = xmlStrcat(*buf, BAD_CAST " '");
760 *buf = xmlStrcat(*buf, item->name);
761 *buf = xmlStrcat(*buf, BAD_CAST "'");
762 } else {
763 *buf = xmlStrdup(xmlSchemaElemDesST);
764 *buf = xmlStrcat(*buf, BAD_CAST " local");
765 }
766 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
767 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
768 *buf = xmlStrdup(xmlSchemaElemDesCT);
769 *buf = xmlStrcat(*buf, BAD_CAST " '");
770 *buf = xmlStrcat(*buf, item->name);
771 *buf = xmlStrcat(*buf, BAD_CAST "'");
772 } else {
773 *buf = xmlStrdup(xmlSchemaElemDesCT);
774 *buf = xmlStrcat(*buf, BAD_CAST " local");
775 }
776 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
777 xmlSchemaAttributePtr attr;
778
779 attr = (xmlSchemaAttributePtr) item;
780 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
781 (attr->ref == NULL)) {
782 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
783 *buf = xmlStrcat(*buf, BAD_CAST " '");
784 *buf = xmlStrcat(*buf, attr->name);
785 *buf = xmlStrcat(*buf, BAD_CAST "'");
786 } else {
787 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
788 *buf = xmlStrcat(*buf, BAD_CAST " '");
789 *buf = xmlStrcat(*buf, attr->refPrefix);
790 *buf = xmlStrcat(*buf, BAD_CAST ":");
791 *buf = xmlStrcat(*buf, attr->ref);
792 *buf = xmlStrcat(*buf, BAD_CAST "'");
793 }
794 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
795 xmlSchemaElementPtr elem;
796
797 elem = (xmlSchemaElementPtr) item;
798 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
799 (elem->ref == NULL)) {
800 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
801 *buf = xmlStrcat(*buf, BAD_CAST " '");
802 *buf = xmlStrcat(*buf, elem->name);
803 *buf = xmlStrcat(*buf, BAD_CAST "'");
804 } else {
805 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
806 *buf = xmlStrcat(*buf, BAD_CAST " '");
807 *buf = xmlStrcat(*buf, elem->refPrefix);
808 *buf = xmlStrcat(*buf, BAD_CAST ":");
809 *buf = xmlStrcat(*buf, elem->ref);
810 *buf = xmlStrcat(*buf, BAD_CAST "'");
811 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000812 } else
813 named = 0;
814 } else
815 named = 0;
816
817 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000818 xmlNodePtr elem;
819
820 if (itemNode->type == XML_ATTRIBUTE_NODE)
821 elem = itemNode->parent;
822 else
823 elem = itemNode;
824 *buf = xmlStrdup(BAD_CAST "Element '");
825 if (parsing)
826 *buf = xmlStrcat(*buf, elem->name);
827 else
828 *buf = xmlStrcat(*buf,
829 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
830 *buf = xmlStrcat(*buf, BAD_CAST "'");
831 }
832 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
833 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
834 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
835 itemNode->ns, itemNode->name));
836 *buf = xmlStrcat(*buf, BAD_CAST "'");
837 }
838 FREE_AND_NULL(str);
839
840 return (*buf);
841}
842
843/**
844 * xmlSchemaPFormatItemDes:
845 * @buf: the string buffer
846 * @item: the item as a schema object
847 * @itemNode: the item as a node
848 *
849 * If the pointer to @buf is not NULL and @but holds no value,
850 * the value is set to a item designation using
851 * xmlSchemaFormatItemForReport. This one avoids adding
852 * an attribute designation postfix.
853 *
854 * Returns a string of all enumeration elements.
855 */
856static void
857xmlSchemaPRequestItemDes(xmlChar **buf,
858 xmlSchemaTypePtr item,
859 xmlNodePtr itemNode)
860{
861 if ((buf == 0) || (*buf != NULL))
862 return;
863 if (itemNode->type == XML_ATTRIBUTE_NODE)
864 itemNode = itemNode->parent;
865 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
866}
867
868/**
869 * xmlSchemaFormatFacetEnumSet:
870 * @buf: the string buffer
871 * @type: the type holding the enumeration facets
872 *
873 * Builds a string consisting of all enumeration elements.
874 *
875 * Returns a string of all enumeration elements.
876 */
877static const xmlChar *
878xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
879{
880 xmlSchemaFacetLinkPtr link;
881
882 if (*buf != NULL)
883 xmlFree(*buf);
884 *buf = NULL;
885 for (link = type->facetSet; link != NULL; link = link->next) {
886 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
887 if (*buf == NULL) {
888 *buf = xmlStrdup(BAD_CAST "'");
889 *buf = xmlStrcat(*buf, link->facet->value);
890 *buf = xmlStrcat(*buf, BAD_CAST "'");
891 } else {
892 *buf = xmlStrcat(*buf, BAD_CAST ", '");
893 *buf = xmlStrcat(*buf, link->facet->value);
894 *buf = xmlStrcat(*buf, BAD_CAST "'");
895 }
896 }
897 }
898 return ((const xmlChar *) *buf);
899}
900
901/**
902 * xmlSchemaVFacetErr:
903 * @ctxt: the schema validation context
904 * @error: the error code
905 * @node: the node to be validated
906 * @value: the value of the node
907 * @type: the type holding the facet
908 * @facet: the facet
909 * @message: the error message of NULL
910 * @str1: extra data
911 * @str2: extra data
912 * @str3: extra data
913 *
914 * Reports a facet validation error.
915 * TODO: Should this report the value of an element as well?
916 */
917static void
918xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
919 xmlParserErrors error,
920 xmlNodePtr node,
921 const xmlChar *value,
922 unsigned long length,
923 xmlSchemaTypePtr type,
924 xmlSchemaFacetPtr facet,
925 const char *message,
926 const xmlChar *str1,
927 const xmlChar *str2,
928 const xmlChar *str3)
929{
930 xmlChar *str = NULL, *msg = NULL;
931 xmlSchemaTypeType facetType;
932
933 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
934 msg = xmlStrcat(msg, BAD_CAST " [");
935 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
936 msg = xmlStrcat(msg, BAD_CAST ", facet '");
937 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
938 facetType = XML_SCHEMA_FACET_ENUMERATION;
939 /*
940 * If enumerations are validated, one must not expect the
941 * facet to be given.
942 */
943 } else
944 facetType = facet->type;
945 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
946 msg = xmlStrcat(msg, BAD_CAST "']: ");
947 if (message == NULL) {
948 /*
949 * Use a default message.
950 */
951 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
952 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
953 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
954
955 char len[25], actLen[25];
956
957 /* FIXME, TODO: What is the max expected string length of the
958 * this value?
959 */
960 if (node->type == XML_ATTRIBUTE_NODE)
961 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
962 else
963 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
964
965 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
966 snprintf(actLen, 24, "%lu", length);
967
968 if (facetType == XML_SCHEMA_FACET_LENGTH)
969 msg = xmlStrcat(msg,
970 BAD_CAST "this differs from the allowed length of '%s'.\n");
971 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
972 msg = xmlStrcat(msg,
973 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
974 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
975 msg = xmlStrcat(msg,
976 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
977
978 if (node->type == XML_ATTRIBUTE_NODE)
979 xmlSchemaVErrExt(ctxt, node, error,
980 (const char *) msg,
981 value, (const xmlChar *) actLen, (const xmlChar *) len,
982 NULL, NULL);
983 else
984 xmlSchemaVErr(ctxt, node, error,
985 (const char *) msg,
986 (const xmlChar *) actLen, (const xmlChar *) len);
987
988 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
989 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
990 "of the set {%s}.\n");
991 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
992 xmlSchemaFormatFacetEnumSet(&str, type));
993 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
994 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
995 "by the pattern '%s'.\n");
996 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
997 facet->value);
998 } else if (node->type == XML_ATTRIBUTE_NODE) {
999 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1000 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1001 } else {
1002 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1003 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1004 }
1005 } else {
1006 msg = xmlStrcat(msg, (const xmlChar *) message);
1007 msg = xmlStrcat(msg, BAD_CAST ".\n");
1008 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1009 }
1010 FREE_AND_NULL(str)
1011 xmlFree(msg);
1012}
1013
1014/**
1015 * xmlSchemaVSimpleTypeErr:
1016 * @ctxt: the schema validation context
1017 * @error: the error code
1018 * @type: the type used for validation
1019 * @node: the node containing the validated value
1020 * @value: the validated value
1021 *
1022 * Reports a simple type validation error.
1023 * TODO: Should this report the value of an element as well?
1024 */
1025static void
1026xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1027 xmlParserErrors error,
1028 xmlNodePtr node,
1029 const xmlChar *value,
1030 xmlSchemaTypePtr type)
1031{
1032 xmlChar *str = NULL, *msg = NULL;
1033
1034 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1035 msg = xmlStrcat(msg, BAD_CAST " [");
1036 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1037 if (node->type == XML_ATTRIBUTE_NODE) {
1038 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1039 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1040 } else {
1041 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1042 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1043 }
1044 FREE_AND_NULL(str)
1045 xmlFree(msg);
1046}
1047
1048/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001049 * xmlSchemaVComplexTypeErr:
1050 * @ctxt: the schema validation context
1051 * @error: the error code
1052 * @node: the node containing the validated value
1053 * @type: the complex type used for validation
1054 * @message: the error message
1055 *
1056 * Reports a complex type validation error.
1057 */
1058static void
1059xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1060 xmlParserErrors error,
1061 xmlNodePtr node,
1062 xmlSchemaTypePtr type,
1063 const char *message)
1064{
1065 xmlChar *str = NULL, *msg = NULL;
1066
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001067 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1068 if (type != NULL) {
1069 msg = xmlStrcat(msg, BAD_CAST " [");
1070 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1071 msg = xmlStrcat(msg, BAD_CAST "]");
1072 }
1073 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
William M. Brack2f2a6632004-08-20 23:09:47 +00001074 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
1075 (const xmlChar *) message, NULL);
1076 FREE_AND_NULL(str)
1077 xmlFree(msg);
1078}
1079
1080/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001081 * xmlSchemaPMissingAttrErr:
1082 * @ctxt: the schema validation context
1083 * @ownerDes: the designation of the owner
1084 * @ownerName: the name of the owner
1085 * @ownerItem: the owner as a schema object
1086 * @ownerElem: the owner as an element node
1087 * @node: the parent element node of the missing attribute node
1088 * @type: the corresponding type of the attribute node
1089 *
1090 * Reports an illegal attribute.
1091 */
1092static void
1093xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1094 xmlParserErrors error,
1095 xmlChar **ownerDes,
1096 xmlSchemaTypePtr ownerItem,
1097 xmlNodePtr ownerElem,
1098 const char *name,
1099 const char *message)
1100{
1101 xmlChar *des = NULL;
1102
1103 if (ownerDes == NULL)
1104 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1105 else if (*ownerDes == NULL) {
1106 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1107 des = *ownerDes;
1108 } else
1109 des = *ownerDes;
1110 if (message != NULL)
1111 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1112 else
1113 xmlSchemaPErr(ctxt, ownerElem, error,
1114 "%s: The attribute '%s' is required but missing.\n",
1115 BAD_CAST des, BAD_CAST name);
1116 if (ownerDes == NULL)
1117 FREE_AND_NULL(des);
1118}
1119
William M. Brack2f2a6632004-08-20 23:09:47 +00001120/**
1121 * xmlSchemaCompTypeToString:
1122 * @type: the type of the schema item
1123 *
1124 * Returns the component name of a schema item.
1125 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001126static const char *
1127xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1128{
1129 switch (type) {
1130 case XML_SCHEMA_TYPE_SIMPLE:
1131 return("simple type definition");
1132 case XML_SCHEMA_TYPE_COMPLEX:
1133 return("complex type definition");
1134 case XML_SCHEMA_TYPE_ELEMENT:
1135 return("element declaration");
1136 case XML_SCHEMA_TYPE_ATTRIBUTE:
1137 return("attribute declaration");
1138 case XML_SCHEMA_TYPE_GROUP:
1139 return("model group definition");
1140 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1141 return("attribute group definition");
1142 case XML_SCHEMA_TYPE_NOTATION:
1143 return("notation declaration");
1144 default:
1145 return("Not a schema component");
1146 }
1147}
1148/**
1149 * xmlSchemaPResCompAttrErr:
1150 * @ctxt: the schema validation context
1151 * @error: the error code
1152 * @ownerDes: the designation of the owner
1153 * @ownerItem: the owner as a schema object
1154 * @ownerElem: the owner as an element node
1155 * @name: the name of the attribute holding the QName
1156 * @refName: the referenced local name
1157 * @refURI: the referenced namespace URI
1158 * @message: optional message
1159 *
1160 * Used to report QName attribute values that failed to resolve
1161 * to schema components.
1162 */
1163static void
1164xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1165 xmlParserErrors error,
1166 xmlChar **ownerDes,
1167 xmlSchemaTypePtr ownerItem,
1168 xmlNodePtr ownerElem,
1169 const char *name,
1170 const xmlChar *refName,
1171 const xmlChar *refURI,
1172 xmlSchemaTypeType refType,
1173 const char *refTypeStr)
1174{
1175 xmlChar *des = NULL, *strA = NULL;
1176
1177 if (ownerDes == NULL)
1178 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1179 else if (*ownerDes == NULL) {
1180 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1181 des = *ownerDes;
1182 } else
1183 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001184 if (refTypeStr == NULL)
1185 refTypeStr = xmlSchemaCompTypeToString(refType);
1186 xmlSchemaPErrExt(ctxt, ownerElem, error,
1187 NULL, NULL, NULL,
1188 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1189 "%s.\n", BAD_CAST des, BAD_CAST name,
1190 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1191 BAD_CAST refTypeStr, NULL);
1192 if (ownerDes == NULL)
1193 FREE_AND_NULL(des)
1194 FREE_AND_NULL(strA)
1195}
1196
William M. Brack2f2a6632004-08-20 23:09:47 +00001197/**
1198 * xmlSchemaPCustomAttrErr:
1199 * @ctxt: the schema parser context
1200 * @error: the error code
1201 * @ownerDes: the designation of the owner
1202 * @ownerItem: the owner as a schema object
1203 * @attr: the illegal attribute node
1204 *
1205 * Reports an illegal attribute during the parse.
1206 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001207static void
1208xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001209 xmlParserErrors error,
1210 xmlChar **ownerDes,
1211 xmlSchemaTypePtr ownerItem,
1212 xmlAttrPtr attr,
1213 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001214{
1215 xmlChar *des = NULL;
1216
1217 if (ownerDes == NULL)
1218 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1219 else if (*ownerDes == NULL) {
1220 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1221 des = *ownerDes;
1222 } else
1223 des = *ownerDes;
1224 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1225 "%s, attribute '%s': %s.\n",
1226 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1227 if (ownerDes == NULL)
1228 FREE_AND_NULL(des);
1229}
1230
1231/**
1232 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001233 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001234 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001235 * @ownerDes: the designation of the attribute's owner
1236 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001237 * @attr: the illegal attribute node
1238 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001239 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001240 */
1241static void
1242xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1243 xmlParserErrors error,
1244 xmlChar **ownerDes,
1245 xmlSchemaTypePtr ownerItem,
1246 xmlAttrPtr attr)
1247{
1248 xmlChar *des = NULL, *strA = NULL;
1249
1250 if (ownerDes == NULL)
1251 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1252 else if (*ownerDes == NULL) {
1253 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1254 des = *ownerDes;
1255 } else
1256 des = *ownerDes;
1257 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1258 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1259 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1260 if (ownerDes == NULL)
1261 FREE_AND_NULL(des);
1262 FREE_AND_NULL(strA);
1263}
1264
William M. Brack2f2a6632004-08-20 23:09:47 +00001265/**
1266 * xmlSchemaPAquireDes:
1267 * @des: the first designation
1268 * @itemDes: the second designation
1269 * @item: the schema item
1270 * @itemElem: the node of the schema item
1271 *
1272 * Creates a designation for an item.
1273 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001274static void
1275xmlSchemaPAquireDes(xmlChar **des,
1276 xmlChar **itemDes,
1277 xmlSchemaTypePtr item,
1278 xmlNodePtr itemElem)
1279{
1280 if (itemDes == NULL)
1281 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1282 else if (*itemDes == NULL) {
1283 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1284 *des = *itemDes;
1285 } else
1286 *des = *itemDes;
1287}
1288
William M. Brack2f2a6632004-08-20 23:09:47 +00001289/**
1290 * xmlSchemaPCustomErr:
1291 * @ctxt: the schema parser context
1292 * @error: the error code
1293 * @itemDes: the designation of the schema item
1294 * @item: the schema item
1295 * @itemElem: the node of the schema item
1296 * @message: the error message
1297 * @str1: an optional param for the error message
1298 * @str2: an optional param for the error message
1299 * @str3: an optional param for the error message
1300 *
1301 * Reports an error during parsing.
1302 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001303static void
1304xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1305 xmlParserErrors error,
1306 xmlChar **itemDes,
1307 xmlSchemaTypePtr item,
1308 xmlNodePtr itemElem,
1309 const char *message,
1310 const xmlChar *str1,
1311 const xmlChar *str2,
1312 const xmlChar *str3)
1313{
1314 xmlChar *des = NULL, *msg = NULL;
1315
1316 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1317 msg = xmlStrdup(BAD_CAST "%s: ");
1318 msg = xmlStrcat(msg, (const xmlChar *) message);
1319 msg = xmlStrcat(msg, BAD_CAST ".\n");
1320 if ((itemElem == NULL) && (item != NULL))
1321 itemElem = item->node;
1322 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1323 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1324 if (itemDes == NULL)
1325 FREE_AND_NULL(des);
1326 FREE_AND_NULL(msg);
1327}
1328
William M. Brack2f2a6632004-08-20 23:09:47 +00001329/**
1330 * xmlSchemaPCustomErr:
1331 * @ctxt: the schema parser context
1332 * @error: the error code
1333 * @itemDes: the designation of the schema item
1334 * @item: the schema item
1335 * @itemElem: the node of the schema item
1336 * @message: the error message
1337 * @str1: the optional param for the error message
1338 *
1339 * Reports an error during parsing.
1340 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001341static void
1342xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1343 xmlParserErrors error,
1344 xmlChar **itemDes,
1345 xmlSchemaTypePtr item,
1346 xmlNodePtr itemElem,
1347 const char *message,
1348 const xmlChar *str1)
1349{
1350 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1351 str1, NULL, NULL);
1352}
1353
William M. Brack2f2a6632004-08-20 23:09:47 +00001354/**
1355 * xmlSchemaPAttrUseErr:
1356 * @ctxt: the schema parser context
1357 * @error: the error code
1358 * @itemDes: the designation of the schema type
1359 * @item: the schema type
1360 * @itemElem: the node of the schema type
1361 * @attr: the invalid schema attribute
1362 * @message: the error message
1363 * @str1: the optional param for the error message
1364 *
1365 * Reports an attribute use error during parsing.
1366 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001367static void
1368xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1369 xmlParserErrors error,
1370 xmlChar **itemDes,
1371 xmlSchemaTypePtr item,
1372 xmlNodePtr itemElem,
1373 const xmlSchemaAttributePtr attr,
1374 const char *message,
1375 const xmlChar *str1)
1376{
1377 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1378
1379 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1380 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1381 xmlSchemaGetAttrName(attr));
1382 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1383 msg = xmlStrcat(msg, (const xmlChar *) message);
1384 msg = xmlStrcat(msg, BAD_CAST ".\n");
1385 if ((itemElem == NULL) && (item != NULL))
1386 itemElem = item->node;
1387 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1388 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1389 if (itemDes == NULL)
1390 FREE_AND_NULL(des);
1391 FREE_AND_NULL(strA);
1392 xmlFree(msg);
1393}
1394
William M. Brack2f2a6632004-08-20 23:09:47 +00001395/**
1396 * xmlSchemaPIllegalFacetAtomicErr:
1397 * @ctxt: the schema parser context
1398 * @error: the error code
1399 * @itemDes: the designation of the type
1400 * @item: the schema type
1401 * @baseItem: the base type of type
1402 * @facet: the illegal facet
1403 *
1404 * Reports an illegal facet for atomic simple types.
1405 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001406static void
1407xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1408 xmlParserErrors error,
1409 xmlChar **itemDes,
1410 xmlSchemaTypePtr item,
1411 xmlSchemaTypePtr baseItem,
1412 xmlSchemaFacetPtr facet)
1413{
1414 xmlChar *des = NULL, *strT = NULL;
1415
1416 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1417 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1418 "%s: The facet '%s' is not allowed on types derived from the "
1419 "type %s.\n",
1420 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1421 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1422 NULL, NULL);
1423 if (itemDes == NULL)
1424 FREE_AND_NULL(des);
1425 FREE_AND_NULL(strT);
1426}
1427
William M. Brack2f2a6632004-08-20 23:09:47 +00001428/**
1429 * xmlSchemaPIllegalFacetListUnionErr:
1430 * @ctxt: the schema parser context
1431 * @error: the error code
1432 * @itemDes: the designation of the schema item involved
1433 * @item: the schema item involved
1434 * @facet: the illegal facet
1435 *
1436 * Reports an illegal facet for <list> and <union>.
1437 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001438static void
1439xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1440 xmlParserErrors error,
1441 xmlChar **itemDes,
1442 xmlSchemaTypePtr item,
1443 xmlSchemaFacetPtr facet)
1444{
1445 xmlChar *des = NULL, *strT = NULL;
1446
1447 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1448 xmlSchemaPErr(ctxt, item->node, error,
1449 "%s: The facet '%s' is not allowed.\n",
1450 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1451 if (itemDes == NULL)
1452 FREE_AND_NULL(des);
1453 FREE_AND_NULL(strT);
1454}
1455
1456/**
1457 * xmlSchemaPMutualExclAttrErr:
1458 * @ctxt: the schema validation context
1459 * @error: the error code
1460 * @elemDes: the designation of the parent element node
1461 * @attr: the bad attribute node
1462 * @type: the corresponding type of the attribute node
1463 *
1464 * Reports an illegal attribute.
1465 */
1466static void
1467xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1468 xmlParserErrors error,
1469 xmlChar **ownerDes,
1470 xmlSchemaTypePtr ownerItem,
1471 xmlAttrPtr attr,
1472 const char *name1,
1473 const char *name2)
1474{
1475 xmlChar *des = NULL;
1476
1477 if (ownerDes == NULL)
1478 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1479 else if (*ownerDes == NULL) {
1480 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1481 des = *ownerDes;
1482 } else
1483 des = *ownerDes;
1484 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1485 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1486 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1487 if (ownerDes == NULL)
1488 FREE_AND_NULL(des)
1489}
1490
1491/**
1492 * xmlSchemaPSimpleTypeErr:
1493 * @ctxt: the schema validation context
1494 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001495 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001496 * @ownerDes: the designation of the owner
1497 * @ownerItem: the schema object if existent
1498 * @node: the validated node
1499 * @value: the validated value
1500 *
1501 * Reports a simple type validation error.
1502 * TODO: Should this report the value of an element as well?
1503 */
1504static void
1505xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1506 xmlParserErrors error,
1507 xmlChar **ownerDes,
1508 xmlSchemaTypePtr ownerItem,
1509 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001510 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001511 const char *typeDes,
1512 const xmlChar *value,
1513 const char *message,
1514 const xmlChar *str1,
1515 const xmlChar *str2)
1516{
William M. Brack2f2a6632004-08-20 23:09:47 +00001517 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001518
1519 if (ownerDes == NULL)
1520 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1521 else if (*ownerDes == NULL) {
1522 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1523 des = *ownerDes;
1524 } else
1525 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001526 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001527 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001528 if (message == NULL) {
1529 /*
1530 * Use default messages.
1531 */
1532 if (node->type == XML_ATTRIBUTE_NODE) {
1533 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1534 "%s, attribute '%s' [%s]: The value '%s' is not "
1535 "valid.\n",
1536 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1537 node->name), BAD_CAST typeDes, value, NULL);
1538 } else {
1539 xmlSchemaPErr(ctxt, node, error,
1540 "%s [%s]: The character content is not valid.\n",
1541 BAD_CAST des, BAD_CAST typeDes);
1542 }
1543 } else {
1544 xmlChar *msg;
1545
1546 msg = xmlStrdup(BAD_CAST "%s");
1547 if (node->type == XML_ATTRIBUTE_NODE)
1548 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1549 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1550 msg = xmlStrcat(msg, (const xmlChar *) message);
1551 msg = xmlStrcat(msg, BAD_CAST ".\n");
1552 if (node->type == XML_ATTRIBUTE_NODE) {
1553 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1554 (const char *) msg,
1555 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1556 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1557 } else {
1558 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1559 (const char *) msg,
1560 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1561 }
1562 xmlFree(msg);
1563 }
1564 /* Cleanup. */
1565 FREE_AND_NULL(strA)
1566 FREE_AND_NULL(strT)
1567 if (ownerDes == NULL)
1568 FREE_AND_NULL(des)
1569}
1570
William M. Brack2f2a6632004-08-20 23:09:47 +00001571/**
1572 * xmlSchemaPContentErr:
1573 * @ctxt: the schema parser context
1574 * @error: the error code
1575 * @onwerDes: the designation of the holder of the content
1576 * @ownerItem: the owner item of the holder of the content
1577 * @ownerElem: the node of the holder of the content
1578 * @child: the invalid child node
1579 * @message: the optional error message
1580 * @content: the optional string describing the correct content
1581 *
1582 * Reports an error concerning the content of a schema element.
1583 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001584static void
1585xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1586 xmlParserErrors error,
1587 xmlChar **ownerDes,
1588 xmlSchemaTypePtr ownerItem,
1589 xmlNodePtr ownerElem,
1590 xmlNodePtr child,
1591 const char *message,
1592 const char *content)
1593{
1594 xmlChar *des = NULL;
1595
1596 if (ownerDes == NULL)
1597 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1598 else if (*ownerDes == NULL) {
1599 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1600 des = *ownerDes;
1601 } else
1602 des = *ownerDes;
1603 if (message != NULL)
1604 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1605 "%s: %s.\n",
1606 BAD_CAST des, BAD_CAST message);
1607 else {
1608 if (content != NULL) {
1609 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1610 "%s: The content is not valid. Expected is %s.\n",
1611 BAD_CAST des, BAD_CAST content);
1612 } else {
1613 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1614 "%s: The content is not valid.\n",
1615 BAD_CAST des, NULL);
1616 }
1617 }
1618 if (ownerDes == NULL)
1619 FREE_AND_NULL(des)
1620}
1621
1622/**
1623 * xmlSchemaVIllegalAttrErr:
1624 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001625 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001626 * @attr: the illegal attribute node
1627 *
1628 * Reports an illegal attribute.
1629 */
1630static void
1631xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001632 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001633 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001634{
1635 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001636
1637 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1638 error,
1639 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001640 "%s: The attribute '%s' is not allowed.\n",
1641 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1642 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1643 FREE_AND_NULL(strE)
1644 FREE_AND_NULL(strA)
1645}
1646
William M. Brack2f2a6632004-08-20 23:09:47 +00001647/**
1648 * xmlSchemaVCustomErr:
1649 * @ctxt: the schema validation context
1650 * @error: the error code
1651 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001652 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001653 * @message: the error message
1654 * @str1: the optional param for the message
1655 *
1656 * Reports a validation error.
1657 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001658static void
1659xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1660 xmlParserErrors error,
1661 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001662 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001663 const char *message,
1664 const xmlChar *str1)
1665{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001666 xmlChar *msg = NULL, *str = NULL;
1667
1668 if (node == NULL) {
1669 xmlSchemaVErr(ctxt, NULL,
1670 XML_SCHEMAV_INTERNAL,
1671 "Internal error: xmlSchemaVCustomErr, no node "
1672 "given.\n", NULL, NULL);
1673 return;
1674 }
1675 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1676 if (node->type != XML_DOCUMENT_NODE) {
1677 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1678 if (type != NULL) {
1679 msg = xmlStrcat(msg, BAD_CAST " [");
1680 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1681 msg = xmlStrcat(msg, BAD_CAST "]");
1682 }
1683 msg = xmlStrcat(msg, BAD_CAST ": ");
1684 } else
1685 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001686 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001687 msg = xmlStrcat(msg, BAD_CAST ".\n");
1688 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1689 FREE_AND_NULL(msg)
1690 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001691}
1692
William M. Brack2f2a6632004-08-20 23:09:47 +00001693/**
1694 * xmlSchemaWildcardPCToString:
1695 * @pc: the type of processContents
1696 *
1697 * Returns a string representation of the type of
1698 * processContents.
1699 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001700static const char *
1701xmlSchemaWildcardPCToString(int pc)
1702{
1703 switch (pc) {
1704 case XML_SCHEMAS_ANY_SKIP:
1705 return ("skip");
1706 case XML_SCHEMAS_ANY_LAX:
1707 return ("lax");
1708 case XML_SCHEMAS_ANY_STRICT:
1709 return ("strict");
1710 default:
1711 return ("invalid process contents");
1712 }
1713}
1714
William M. Brack2f2a6632004-08-20 23:09:47 +00001715/**
1716 * xmlSchemaVWildcardErr:
1717 * @ctxt: the schema validation context
1718 * @error: the error code
1719 * @node: the validated node
1720 * @wild: the wildcard used
1721 * @message: the error message
1722 *
1723 * Reports an validation-by-wildcard error.
1724 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001725static void
1726xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaWildcardPtr wild,
1730 const char *message)
1731{
1732 xmlChar *des = NULL, *msg = NULL;
1733
1734 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1735 msg = xmlStrdup(BAD_CAST "%s, [");
1736 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
1737 msg = xmlStrcat(msg, BAD_CAST " WC]: ");
1738 msg = xmlStrcat(msg, (const xmlChar *) message);
1739 msg = xmlStrcat(msg, BAD_CAST ".\n");
1740 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1741 FREE_AND_NULL(des);
1742 FREE_AND_NULL(msg);
1743}
1744
1745/**
1746 * xmlSchemaVMissingAttrErr:
1747 * @ctxt: the schema validation context
1748 * @node: the parent element node of the missing attribute node
1749 * @type: the corresponding type of the attribute node
1750 *
1751 * Reports an illegal attribute.
1752 */
1753static void
1754xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1755 xmlNodePtr elem,
1756 xmlSchemaAttributePtr type)
1757{
1758 const xmlChar *name, *uri;
1759 xmlChar *strE = NULL, *strA = NULL;
1760
1761 if (type->ref != NULL) {
1762 name = type->ref;
1763 uri = type->refNs;
1764 } else {
1765 name = type->name;
1766 uri = type->targetNamespace;
1767 }
1768 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001769 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1770 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001771 "%s: The attribute %s is required but missing.\n",
1772 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1773 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1774 FREE_AND_NULL(strE)
1775 FREE_AND_NULL(strA)
1776}
1777
Daniel Veillard4255d502002-04-16 15:50:10 +00001778/************************************************************************
1779 * *
1780 * Allocation functions *
1781 * *
1782 ************************************************************************/
1783
1784/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001785 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001786 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001787 *
1788 * Allocate a new Schema structure.
1789 *
1790 * Returns the newly allocated structure or NULL in case or error
1791 */
1792static xmlSchemaPtr
1793xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1794{
1795 xmlSchemaPtr ret;
1796
1797 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1798 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001799 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001800 return (NULL);
1801 }
1802 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001803 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001804 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001805
1806 return (ret);
1807}
1808
1809/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001810 * xmlSchemaNewSchema:
1811 * @ctxt: a schema validation context
1812 *
1813 * Allocate a new Schema structure.
1814 *
1815 * Returns the newly allocated structure or NULL in case or error
1816 */
1817static xmlSchemaAssemblePtr
1818xmlSchemaNewAssemble(void)
1819{
1820 xmlSchemaAssemblePtr ret;
1821
1822 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1823 if (ret == NULL) {
1824 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1825 return (NULL);
1826 }
1827 memset(ret, 0, sizeof(xmlSchemaAssemble));
1828 ret->items = NULL;
1829 return (ret);
1830}
1831
1832/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001833 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001834 *
1835 * Allocate a new Facet structure.
1836 *
1837 * Returns the newly allocated structure or NULL in case or error
1838 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001839xmlSchemaFacetPtr
1840xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001841{
1842 xmlSchemaFacetPtr ret;
1843
1844 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1845 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001846 return (NULL);
1847 }
1848 memset(ret, 0, sizeof(xmlSchemaFacet));
1849
1850 return (ret);
1851}
1852
1853/**
1854 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001855 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001856 * @node: a node
1857 *
1858 * Allocate a new annotation structure.
1859 *
1860 * Returns the newly allocated structure or NULL in case or error
1861 */
1862static xmlSchemaAnnotPtr
1863xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1864{
1865 xmlSchemaAnnotPtr ret;
1866
1867 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1868 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001869 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001870 return (NULL);
1871 }
1872 memset(ret, 0, sizeof(xmlSchemaAnnot));
1873 ret->content = node;
1874 return (ret);
1875}
1876
1877/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001878 * xmlSchemaFreeAnnot:
1879 * @annot: a schema type structure
1880 *
1881 * Deallocate a annotation structure
1882 */
1883static void
1884xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1885{
1886 if (annot == NULL)
1887 return;
1888 xmlFree(annot);
1889}
1890
1891/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001892 * xmlSchemaFreeImport:
1893 * @import: a schema import structure
1894 *
1895 * Deallocate an import structure
1896 */
1897static void
1898xmlSchemaFreeImport(xmlSchemaImportPtr import)
1899{
1900 if (import == NULL)
1901 return;
1902
1903 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001904 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001905 xmlFree(import);
1906}
1907
1908/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001909 * xmlSchemaFreeInclude:
1910 * @include: a schema include structure
1911 *
1912 * Deallocate an include structure
1913 */
1914static void
1915xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1916{
1917 if (include == NULL)
1918 return;
1919
1920 xmlFreeDoc(include->doc);
1921 xmlFree(include);
1922}
1923
1924/**
1925 * xmlSchemaFreeIncludeList:
1926 * @includes: a schema include list
1927 *
1928 * Deallocate an include structure
1929 */
1930static void
1931xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1932{
1933 xmlSchemaIncludePtr next;
1934
1935 while (includes != NULL) {
1936 next = includes->next;
1937 xmlSchemaFreeInclude(includes);
1938 includes = next;
1939 }
1940}
1941
1942/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001943 * xmlSchemaFreeNotation:
1944 * @schema: a schema notation structure
1945 *
1946 * Deallocate a Schema Notation structure.
1947 */
1948static void
1949xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1950{
1951 if (nota == NULL)
1952 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001953 xmlFree(nota);
1954}
1955
1956/**
1957 * xmlSchemaFreeAttribute:
1958 * @schema: a schema attribute structure
1959 *
1960 * Deallocate a Schema Attribute structure.
1961 */
1962static void
1963xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
1964{
1965 if (attr == NULL)
1966 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001967 if (attr->annot != NULL)
1968 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001969 if (attr->defVal != NULL)
1970 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00001971 xmlFree(attr);
1972}
1973
1974/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001975 * xmlSchemaFreeWildcardNsSet:
1976 * set: a schema wildcard namespace
1977 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001978 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00001979 */
1980static void
1981xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
1982{
1983 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001984
Daniel Veillard3646d642004-06-02 19:19:14 +00001985 while (set != NULL) {
1986 next = set->next;
1987 xmlFree(set);
1988 set = next;
1989 }
1990}
1991
1992/**
1993 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001994 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00001995 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001996 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00001997 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00001998void
Daniel Veillard3646d642004-06-02 19:19:14 +00001999xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2000{
2001 if (wildcard == NULL)
2002 return;
2003 if (wildcard->annot != NULL)
2004 xmlSchemaFreeAnnot(wildcard->annot);
2005 if (wildcard->nsSet != NULL)
2006 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2007 if (wildcard->negNsSet != NULL)
2008 xmlFree(wildcard->negNsSet);
2009 xmlFree(wildcard);
2010}
2011
2012/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002013 * xmlSchemaFreeAttributeGroup:
2014 * @schema: a schema attribute group structure
2015 *
2016 * Deallocate a Schema Attribute Group structure.
2017 */
2018static void
2019xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2020{
2021 if (attr == NULL)
2022 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002023 if (attr->annot != NULL)
2024 xmlSchemaFreeAnnot(attr->annot);
2025 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2026 (attr->attributeWildcard != NULL))
2027 xmlSchemaFreeWildcard(attr->attributeWildcard);
2028
Daniel Veillard4255d502002-04-16 15:50:10 +00002029 xmlFree(attr);
2030}
2031
2032/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002033 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002034 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002035 *
2036 * Deallocate a list of schema attribute uses.
2037 */
2038static void
2039xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2040{
2041 xmlSchemaAttributeLinkPtr next;
2042
2043 while (attrUse != NULL) {
2044 next = attrUse->next;
2045 xmlFree(attrUse);
2046 attrUse = next;
2047 }
2048}
2049
2050/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002051 * xmlSchemaFreeTypeLinkList:
2052 * @alink: a type link
2053 *
2054 * Deallocate a list of types.
2055 */
2056static void
2057xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2058{
2059 xmlSchemaTypeLinkPtr next;
2060
2061 while (link != NULL) {
2062 next = link->next;
2063 xmlFree(link);
2064 link = next;
2065 }
2066}
2067
2068/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002069 * xmlSchemaFreeElement:
2070 * @schema: a schema element structure
2071 *
2072 * Deallocate a Schema Element structure.
2073 */
2074static void
2075xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2076{
2077 if (elem == NULL)
2078 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002079 if (elem->annot != NULL)
2080 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002081 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002082 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002083 if (elem->defVal != NULL)
2084 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002085 xmlFree(elem);
2086}
2087
2088/**
2089 * xmlSchemaFreeFacet:
2090 * @facet: a schema facet structure
2091 *
2092 * Deallocate a Schema Facet structure.
2093 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002094void
Daniel Veillard4255d502002-04-16 15:50:10 +00002095xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2096{
2097 if (facet == NULL)
2098 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002099 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002100 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002101 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002102 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002103 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002104 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002105 xmlFree(facet);
2106}
2107
2108/**
2109 * xmlSchemaFreeType:
2110 * @type: a schema type structure
2111 *
2112 * Deallocate a Schema Type structure.
2113 */
2114void
2115xmlSchemaFreeType(xmlSchemaTypePtr type)
2116{
2117 if (type == NULL)
2118 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002119 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002120 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002121 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002122 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002123
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002124 facet = type->facets;
2125 while (facet != NULL) {
2126 next = facet->next;
2127 xmlSchemaFreeFacet(facet);
2128 facet = next;
2129 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002130 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002131 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2132 if (type->attributeUses != NULL)
2133 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002134 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002135 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002136 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2137 /*
2138 * NOTE: The only case where an attribute wildcard
2139 * is not owned, is if a complex type inherits it
2140 * from a base type.
2141 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002142 xmlSchemaFreeWildcard(type->attributeWildcard);
2143 }
2144 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002145 if (type->memberTypes != NULL)
2146 xmlSchemaFreeTypeLinkList(type->memberTypes);
2147 if (type->facetSet != NULL) {
2148 xmlSchemaFacetLinkPtr next, link;
2149
2150 link = type->facetSet;
2151 do {
2152 next = link->next;
2153 xmlFree(link);
2154 link = next;
2155 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002156 }
2157 if (type->contModel != NULL)
2158 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 xmlFree(type);
2160}
2161
2162/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002163 * xmlSchemaFreeTypeList:
2164 * @type: a schema type structure
2165 *
2166 * Deallocate a Schema Type structure.
2167 */
2168static void
2169xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2170{
2171 xmlSchemaTypePtr next;
2172
2173 while (type != NULL) {
2174 next = type->redef;
2175 xmlSchemaFreeType(type);
2176 type = next;
2177 }
2178}
2179
2180/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002181 * xmlSchemaFree:
2182 * @schema: a schema structure
2183 *
2184 * Deallocate a Schema structure.
2185 */
2186void
2187xmlSchemaFree(xmlSchemaPtr schema)
2188{
2189 if (schema == NULL)
2190 return;
2191
Daniel Veillard4255d502002-04-16 15:50:10 +00002192 if (schema->notaDecl != NULL)
2193 xmlHashFree(schema->notaDecl,
2194 (xmlHashDeallocator) xmlSchemaFreeNotation);
2195 if (schema->attrDecl != NULL)
2196 xmlHashFree(schema->attrDecl,
2197 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2198 if (schema->attrgrpDecl != NULL)
2199 xmlHashFree(schema->attrgrpDecl,
2200 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2201 if (schema->elemDecl != NULL)
2202 xmlHashFree(schema->elemDecl,
2203 (xmlHashDeallocator) xmlSchemaFreeElement);
2204 if (schema->typeDecl != NULL)
2205 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002206 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002207 if (schema->groupDecl != NULL)
2208 xmlHashFree(schema->groupDecl,
2209 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002210 if (schema->schemasImports != NULL)
2211 xmlHashFree(schema->schemasImports,
2212 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002213 if (schema->includes != NULL) {
2214 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2215 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002216 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002217 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002218 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002219 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002220 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002221 xmlFree(schema);
2222}
2223
2224/************************************************************************
2225 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002226 * Debug functions *
2227 * *
2228 ************************************************************************/
2229
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002230#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231
Daniel Veillard4255d502002-04-16 15:50:10 +00002232/**
2233 * xmlSchemaElementDump:
2234 * @elem: an element
2235 * @output: the file output
2236 *
2237 * Dump the element
2238 */
2239static void
2240xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002241 const xmlChar * name ATTRIBUTE_UNUSED,
2242 const xmlChar * context ATTRIBUTE_UNUSED,
2243 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002244{
2245 if (elem == NULL)
2246 return;
2247
2248 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002249 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2250 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 fprintf(output, ": %s ", elem->name);
2252 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 fprintf(output, "namespace '%s' ", namespace);
2254
Daniel Veillard4255d502002-04-16 15:50:10 +00002255 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002256 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002257 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002258 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002259 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002260 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002261 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002262 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002263 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002264 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002265 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002266 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002267 fprintf(output, "\n");
2268 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002269 fprintf(output, " ");
2270 if (elem->minOccurs != 1)
2271 fprintf(output, "min: %d ", elem->minOccurs);
2272 if (elem->maxOccurs >= UNBOUNDED)
2273 fprintf(output, "max: unbounded\n");
2274 else if (elem->maxOccurs != 1)
2275 fprintf(output, "max: %d\n", elem->maxOccurs);
2276 else
2277 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002278 }
2279 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002280 fprintf(output, " type: %s", elem->namedType);
2281 if (elem->namedTypeNs != NULL)
2282 fprintf(output, " ns %s\n", elem->namedTypeNs);
2283 else
2284 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002285 }
2286 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002287 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2288 if (elem->substGroupNs != NULL)
2289 fprintf(output, " ns %s\n", elem->substGroupNs);
2290 else
2291 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002292 }
2293 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002294 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002295}
2296
2297/**
2298 * xmlSchemaAnnotDump:
2299 * @output: the file output
2300 * @annot: a annotation
2301 *
2302 * Dump the annotation
2303 */
2304static void
2305xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2306{
2307 xmlChar *content;
2308
2309 if (annot == NULL)
2310 return;
2311
2312 content = xmlNodeGetContent(annot->content);
2313 if (content != NULL) {
2314 fprintf(output, " Annot: %s\n", content);
2315 xmlFree(content);
2316 } else
2317 fprintf(output, " Annot: empty\n");
2318}
2319
2320/**
2321 * xmlSchemaTypeDump:
2322 * @output: the file output
2323 * @type: a type structure
2324 *
2325 * Dump a SchemaType structure
2326 */
2327static void
2328xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2329{
2330 if (type == NULL) {
2331 fprintf(output, "Type: NULL\n");
2332 return;
2333 }
2334 fprintf(output, "Type: ");
2335 if (type->name != NULL)
2336 fprintf(output, "%s, ", type->name);
2337 else
2338 fprintf(output, "no name");
2339 switch (type->type) {
2340 case XML_SCHEMA_TYPE_BASIC:
2341 fprintf(output, "basic ");
2342 break;
2343 case XML_SCHEMA_TYPE_SIMPLE:
2344 fprintf(output, "simple ");
2345 break;
2346 case XML_SCHEMA_TYPE_COMPLEX:
2347 fprintf(output, "complex ");
2348 break;
2349 case XML_SCHEMA_TYPE_SEQUENCE:
2350 fprintf(output, "sequence ");
2351 break;
2352 case XML_SCHEMA_TYPE_CHOICE:
2353 fprintf(output, "choice ");
2354 break;
2355 case XML_SCHEMA_TYPE_ALL:
2356 fprintf(output, "all ");
2357 break;
2358 case XML_SCHEMA_TYPE_UR:
2359 fprintf(output, "ur ");
2360 break;
2361 case XML_SCHEMA_TYPE_RESTRICTION:
2362 fprintf(output, "restriction ");
2363 break;
2364 case XML_SCHEMA_TYPE_EXTENSION:
2365 fprintf(output, "extension ");
2366 break;
2367 default:
2368 fprintf(output, "unknowntype%d ", type->type);
2369 break;
2370 }
2371 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002372 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002373 }
2374 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002375 case XML_SCHEMA_CONTENT_UNKNOWN:
2376 fprintf(output, "unknown ");
2377 break;
2378 case XML_SCHEMA_CONTENT_EMPTY:
2379 fprintf(output, "empty ");
2380 break;
2381 case XML_SCHEMA_CONTENT_ELEMENTS:
2382 fprintf(output, "element ");
2383 break;
2384 case XML_SCHEMA_CONTENT_MIXED:
2385 fprintf(output, "mixed ");
2386 break;
2387 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002388 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002389 break;
2390 case XML_SCHEMA_CONTENT_BASIC:
2391 fprintf(output, "basic ");
2392 break;
2393 case XML_SCHEMA_CONTENT_SIMPLE:
2394 fprintf(output, "simple ");
2395 break;
2396 case XML_SCHEMA_CONTENT_ANY:
2397 fprintf(output, "any ");
2398 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002399 }
2400 fprintf(output, "\n");
2401 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002402 fprintf(output, " ");
2403 if (type->minOccurs != 1)
2404 fprintf(output, "min: %d ", type->minOccurs);
2405 if (type->maxOccurs >= UNBOUNDED)
2406 fprintf(output, "max: unbounded\n");
2407 else if (type->maxOccurs != 1)
2408 fprintf(output, "max: %d\n", type->maxOccurs);
2409 else
2410 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002411 }
2412 if (type->annot != NULL)
2413 xmlSchemaAnnotDump(output, type->annot);
2414 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002416
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002417 fprintf(output, " subtypes: ");
2418 while (sub != NULL) {
2419 fprintf(output, "%s ", sub->name);
2420 sub = sub->next;
2421 }
2422 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002423 }
2424
2425}
2426
2427/**
2428 * xmlSchemaDump:
2429 * @output: the file output
2430 * @schema: a schema structure
2431 *
2432 * Dump a Schema structure.
2433 */
2434void
2435xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2436{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002437 if (output == NULL)
2438 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002439 if (schema == NULL) {
2440 fprintf(output, "Schemas: NULL\n");
2441 return;
2442 }
2443 fprintf(output, "Schemas: ");
2444 if (schema->name != NULL)
2445 fprintf(output, "%s, ", schema->name);
2446 else
2447 fprintf(output, "no name, ");
2448 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002449 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002450 else
2451 fprintf(output, "no target namespace");
2452 fprintf(output, "\n");
2453 if (schema->annot != NULL)
2454 xmlSchemaAnnotDump(output, schema->annot);
2455
2456 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2457 output);
2458 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002459 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002460}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002461#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002462
2463/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002464 * *
2465 * Utilities *
2466 * *
2467 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002468
Daniel Veillardc0826a72004-08-10 14:17:33 +00002469/**
2470 * xmlSchemaGetPropNode:
2471 * @node: the element node
2472 * @name: the name of the attribute
2473 *
2474 * Seeks an attribute with a name of @name in
2475 * no namespace.
2476 *
2477 * Returns the attribute or NULL if not present.
2478 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002479static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002480xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002481{
2482 xmlAttrPtr prop;
2483
Daniel Veillardc0826a72004-08-10 14:17:33 +00002484 if ((node == NULL) || (name == NULL))
2485 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002486 prop = node->properties;
2487 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002488 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2489 return(prop);
2490 prop = prop->next;
2491 }
2492 return (NULL);
2493}
2494
2495/**
2496 * xmlSchemaGetPropNodeNs:
2497 * @node: the element node
2498 * @uri: the uri
2499 * @name: the name of the attribute
2500 *
2501 * Seeks an attribute with a local name of @name and
2502 * a namespace URI of @uri.
2503 *
2504 * Returns the attribute or NULL if not present.
2505 */
2506static xmlAttrPtr
2507xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2508{
2509 xmlAttrPtr prop;
2510
2511 if ((node == NULL) || (name == NULL))
2512 return(NULL);
2513 prop = node->properties;
2514 while (prop != NULL) {
2515 if ((prop->ns != NULL) &&
2516 xmlStrEqual(prop->name, BAD_CAST name) &&
2517 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002518 return(prop);
2519 prop = prop->next;
2520 }
2521 return (NULL);
2522}
2523
2524static const xmlChar *
2525xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2526{
2527 xmlChar *val;
2528 const xmlChar *ret;
2529
2530 val = xmlNodeGetContent(node);
2531 if (val == NULL)
2532 return(NULL);
2533 ret = xmlDictLookup(ctxt->dict, val, -1);
2534 xmlFree(val);
2535 return(ret);
2536}
2537
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002538/**
2539 * xmlSchemaGetProp:
2540 * @ctxt: the parser context
2541 * @node: the node
2542 * @name: the property name
2543 *
2544 * Read a attribute value and internalize the string
2545 *
2546 * Returns the string or NULL if not present.
2547 */
2548static const xmlChar *
2549xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2550 const char *name)
2551{
2552 xmlChar *val;
2553 const xmlChar *ret;
2554
2555 val = xmlGetProp(node, BAD_CAST name);
2556 if (val == NULL)
2557 return(NULL);
2558 ret = xmlDictLookup(ctxt->dict, val, -1);
2559 xmlFree(val);
2560 return(ret);
2561}
2562
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002563/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002564 * *
2565 * Parsing functions *
2566 * *
2567 ************************************************************************/
2568
2569/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002570 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002571 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002572 * @name: the element name
2573 * @ns: the element namespace
2574 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002575 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002576 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002577 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002578 */
2579static xmlSchemaElementPtr
2580xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002581 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002582{
2583 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002584
2585 if ((name == NULL) || (schema == NULL))
2586 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002587
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002588 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002589 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002590 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002591 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002592 } else
2593 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002594 /*
2595 * This one was removed, since top level element declarations have
2596 * the target namespace specified in targetNamespace of the <schema>
2597 * information element, even if elementFormDefault is "unqualified".
2598 */
2599
2600 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002601 if (xmlStrEqual(namespace, schema->targetNamespace))
2602 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2603 else
2604 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002605 if ((ret != NULL) &&
2606 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002607 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002608 }
William M. Bracke7091952004-05-11 15:09:58 +00002609 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002610
William M. Brack2f2a6632004-08-20 23:09:47 +00002611 /*
2612 * Removed since imported components will be hold by the main schema only.
2613 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002614 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002615 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002616 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002617 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002618 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002619 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002620 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2621 return (ret);
2622 } else
2623 ret = NULL;
2624 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002625 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002626#ifdef DEBUG
2627 if (ret == NULL) {
2628 if (namespace == NULL)
2629 fprintf(stderr, "Unable to lookup type %s", name);
2630 else
2631 fprintf(stderr, "Unable to lookup type %s:%s", name,
2632 namespace);
2633 }
2634#endif
2635 return (ret);
2636}
2637
2638/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002639 * xmlSchemaGetType:
2640 * @schema: the schemas context
2641 * @name: the type name
2642 * @ns: the type namespace
2643 *
2644 * Lookup a type in the schemas or the predefined types
2645 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002646 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002647 */
2648static xmlSchemaTypePtr
2649xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002650 const xmlChar * namespace)
2651{
Daniel Veillard4255d502002-04-16 15:50:10 +00002652 xmlSchemaTypePtr ret;
2653
2654 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002656 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002657 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002658 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002659 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002660 }
2661 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002662 if (ret != NULL)
2663 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002664 /*
2665 * Removed, since the imported components will be grafted on the
2666 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002667 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002668 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002669 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002670 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002671 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002672 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002673 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2674 return (ret);
2675 } else
2676 ret = NULL;
2677 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002678 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002679#ifdef DEBUG
2680 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002681 if (namespace == NULL)
2682 fprintf(stderr, "Unable to lookup type %s", name);
2683 else
2684 fprintf(stderr, "Unable to lookup type %s:%s", name,
2685 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002686 }
2687#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002688 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002689}
2690
Daniel Veillard3646d642004-06-02 19:19:14 +00002691/**
2692 * xmlSchemaGetAttribute:
2693 * @schema: the context of the schema
2694 * @name: the name of the attribute
2695 * @ns: the target namespace of the attribute
2696 *
2697 * Lookup a an attribute in the schema or imported schemas
2698 *
2699 * Returns the attribute declaration or NULL if not found.
2700 */
2701static xmlSchemaAttributePtr
2702xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2703 const xmlChar * namespace)
2704{
2705 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002706
2707 if ((name == NULL) || (schema == NULL))
2708 return (NULL);
2709
2710
2711 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2712 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2713 return (ret);
2714 else
2715 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002716 /*
2717 * Removed, since imported components will be hold by the main schema only.
2718 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002719 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002720 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002721 else
2722 import = xmlHashLookup(schema->schemasImports, namespace);
2723 if (import != NULL) {
2724 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2725 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2726 return (ret);
2727 } else
2728 ret = NULL;
2729 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002730 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002731#ifdef DEBUG
2732 if (ret == NULL) {
2733 if (namespace == NULL)
2734 fprintf(stderr, "Unable to lookup attribute %s", name);
2735 else
2736 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2737 namespace);
2738 }
2739#endif
2740 return (ret);
2741}
2742
2743/**
2744 * xmlSchemaGetAttributeGroup:
2745 * @schema: the context of the schema
2746 * @name: the name of the attribute group
2747 * @ns: the target namespace of the attribute group
2748 *
2749 * Lookup a an attribute group in the schema or imported schemas
2750 *
2751 * Returns the attribute group definition or NULL if not found.
2752 */
2753static xmlSchemaAttributeGroupPtr
2754xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2755 const xmlChar * namespace)
2756{
2757 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002758
2759 if ((name == NULL) || (schema == NULL))
2760 return (NULL);
2761
2762
2763 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2764 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2765 return (ret);
2766 else
2767 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002768 /*
2769 * Removed since imported components will be hold by the main schema only.
2770 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002771 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002772 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002773 else
2774 import = xmlHashLookup(schema->schemasImports, namespace);
2775 if (import != NULL) {
2776 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2777 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2778 return (ret);
2779 else
2780 ret = NULL;
2781 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002782 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002783#ifdef DEBUG
2784 if (ret == NULL) {
2785 if (namespace == NULL)
2786 fprintf(stderr, "Unable to lookup attribute group %s", name);
2787 else
2788 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2789 namespace);
2790 }
2791#endif
2792 return (ret);
2793}
2794
2795/**
2796 * xmlSchemaGetGroup:
2797 * @schema: the context of the schema
2798 * @name: the name of the group
2799 * @ns: the target namespace of the group
2800 *
2801 * Lookup a group in the schema or imported schemas
2802 *
2803 * Returns the group definition or NULL if not found.
2804 */
2805static xmlSchemaTypePtr
2806xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2807 const xmlChar * namespace)
2808{
2809 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002810
2811 if ((name == NULL) || (schema == NULL))
2812 return (NULL);
2813
2814
2815 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2816 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2817 return (ret);
2818 else
2819 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002820 /*
2821 * Removed since imported components will be hold by the main schema only.
2822 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002823 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002824 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002825 else
2826 import = xmlHashLookup(schema->schemasImports, namespace);
2827 if (import != NULL) {
2828 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2829 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2830 return (ret);
2831 else
2832 ret = NULL;
2833 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002834 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002835#ifdef DEBUG
2836 if (ret == NULL) {
2837 if (namespace == NULL)
2838 fprintf(stderr, "Unable to lookup group %s", name);
2839 else
2840 fprintf(stderr, "Unable to lookup group %s:%s", name,
2841 namespace);
2842 }
2843#endif
2844 return (ret);
2845}
2846
Daniel Veillard4255d502002-04-16 15:50:10 +00002847/************************************************************************
2848 * *
2849 * Parsing functions *
2850 * *
2851 ************************************************************************/
2852
2853#define IS_BLANK_NODE(n) \
2854 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2855
2856/**
2857 * xmlSchemaIsBlank:
2858 * @str: a string
2859 *
2860 * Check if a string is ignorable
2861 *
2862 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2863 */
2864static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002865xmlSchemaIsBlank(xmlChar * str)
2866{
Daniel Veillard4255d502002-04-16 15:50:10 +00002867 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002868 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002869 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002870 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002871 return (0);
2872 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002873 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002874 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002875}
2876
2877/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002878 * xmlSchemaAddAssembledItem:
2879 * @ctxt: a schema parser context
2880 * @schema: the schema being built
2881 * @item: the item
2882 *
2883 * Add a item to the schema's list of current items.
2884 * This is used if the schema was already constructed and
2885 * new schemata need to be added to it.
2886 * *WARNING* this interface is highly subject to change.
2887 *
2888 * Returns 0 if suceeds and -1 if an internal error occurs.
2889 */
2890static int
2891xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
2892 xmlSchemaTypePtr item)
2893{
2894 static int growSize = 100;
2895 xmlSchemaAssemblePtr ass;
2896
2897 ass = ctxt->assemble;
2898 if (ass->sizeItems < 0) {
2899 /* If disabled. */
2900 return (0);
2901 }
2902 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002903 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002904 if (ass->items == NULL) {
2905 xmlSchemaPErrMemory(ctxt,
2906 "allocating new item buffer", NULL);
2907 return (-1);
2908 }
2909 ass->sizeItems = growSize;
2910 } else if (ass->sizeItems <= ass->nbItems) {
2911 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002912 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002913 ass->sizeItems * sizeof(xmlSchemaTypePtr));
2914 if (ass->items == NULL) {
2915 xmlSchemaPErrMemory(ctxt,
2916 "growing item buffer", NULL);
2917 ass->sizeItems = 0;
2918 return (-1);
2919 }
2920 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002921 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002922 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
2923 return (0);
2924}
2925
2926/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002927 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002928 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 * @schema: the schema being built
2930 * @name: the item name
2931 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002933 * *WARNING* this interface is highly subject to change
2934 *
2935 * Returns the new struture or NULL in case of error
2936 */
2937static xmlSchemaNotationPtr
2938xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002939 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002940{
2941 xmlSchemaNotationPtr ret = NULL;
2942 int val;
2943
2944 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2945 return (NULL);
2946
2947 if (schema->notaDecl == NULL)
2948 schema->notaDecl = xmlHashCreate(10);
2949 if (schema->notaDecl == NULL)
2950 return (NULL);
2951
2952 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2953 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002954 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002955 return (NULL);
2956 }
2957 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002958 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002959 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2960 ret);
2961 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002962 /*
2963 * TODO: This should never happen, since a unique name will be computed.
2964 * If it fails, then an other internal error must have occured.
2965 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002966 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2967 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002968 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002969 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002970 xmlFree(ret);
2971 return (NULL);
2972 }
2973 return (ret);
2974}
2975
2976
2977/**
2978 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002979 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002980 * @schema: the schema being built
2981 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002982 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002983 *
2984 * Add an XML schema Attrribute declaration
2985 * *WARNING* this interface is highly subject to change
2986 *
2987 * Returns the new struture or NULL in case of error
2988 */
2989static xmlSchemaAttributePtr
2990xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002991 const xmlChar * name, const xmlChar * namespace,
2992 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002993{
2994 xmlSchemaAttributePtr ret = NULL;
2995 int val;
2996
2997 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2998 return (NULL);
2999
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003000#ifdef DEBUG
3001 fprintf(stderr, "Adding attribute %s\n", name);
3002 if (namespace != NULL)
3003 fprintf(stderr, " target namespace %s\n", namespace);
3004#endif
3005
Daniel Veillard4255d502002-04-16 15:50:10 +00003006 if (schema->attrDecl == NULL)
3007 schema->attrDecl = xmlHashCreate(10);
3008 if (schema->attrDecl == NULL)
3009 return (NULL);
3010
3011 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3012 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003013 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003014 return (NULL);
3015 }
3016 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003017 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3018 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003020 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003021 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003022 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003023 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003024 NULL, NULL, node,
3025 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003026 xmlFree(ret);
3027 return (NULL);
3028 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003029 if (ctxt->assemble != NULL)
3030 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003031 return (ret);
3032}
3033
3034/**
3035 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003036 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003037 * @schema: the schema being built
3038 * @name: the item name
3039 *
3040 * Add an XML schema Attrribute Group declaration
3041 *
3042 * Returns the new struture or NULL in case of error
3043 */
3044static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003045xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003046 xmlSchemaPtr schema, const xmlChar * name,
3047 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003048{
3049 xmlSchemaAttributeGroupPtr ret = NULL;
3050 int val;
3051
3052 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3053 return (NULL);
3054
3055 if (schema->attrgrpDecl == NULL)
3056 schema->attrgrpDecl = xmlHashCreate(10);
3057 if (schema->attrgrpDecl == NULL)
3058 return (NULL);
3059
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003060 ret =
3061 (xmlSchemaAttributeGroupPtr)
3062 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003063 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003064 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003065 return (NULL);
3066 }
3067 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003068 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003069 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003070 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003071 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003072 xmlSchemaPCustomErr(ctxt,
3073 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3074 NULL, NULL, node,
3075 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003076 xmlFree(ret);
3077 return (NULL);
3078 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003079 if (ctxt->assemble != NULL)
3080 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003081 return (ret);
3082}
3083
3084/**
3085 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003086 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003087 * @schema: the schema being built
3088 * @name: the type name
3089 * @namespace: the type namespace
3090 *
3091 * Add an XML schema Element declaration
3092 * *WARNING* this interface is highly subject to change
3093 *
3094 * Returns the new struture or NULL in case of error
3095 */
3096static xmlSchemaElementPtr
3097xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003098 const xmlChar * name, const xmlChar * namespace,
3099 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003100{
3101 xmlSchemaElementPtr ret = NULL;
3102 int val;
3103
3104 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3105 return (NULL);
3106
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003107#ifdef DEBUG
3108 fprintf(stderr, "Adding element %s\n", name);
3109 if (namespace != NULL)
3110 fprintf(stderr, " target namespace %s\n", namespace);
3111#endif
3112
Daniel Veillard4255d502002-04-16 15:50:10 +00003113 if (schema->elemDecl == NULL)
3114 schema->elemDecl = xmlHashCreate(10);
3115 if (schema->elemDecl == NULL)
3116 return (NULL);
3117
3118 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3119 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003120 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003121 return (NULL);
3122 }
3123 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003124 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3125 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003126 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003127 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003128 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003129 if (topLevel) {
3130 xmlSchemaPCustomErr(ctxt,
3131 XML_SCHEMAP_REDEFINED_ELEMENT,
3132 NULL, NULL, node,
3133 "A global element declaration with the name '%s' does "
3134 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003135 xmlFree(ret);
3136 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003137 } else {
3138 char buf[30];
3139
3140 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3141 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3142 namespace, ret);
3143 if (val != 0) {
3144 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003145 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003146 NULL, NULL, node,
3147 "Internal error: xmlSchemaAddElement, "
3148 "a dublicate element declaration with the name '%s' "
3149 "could not be added to the hash.", name);
3150 xmlFree(ret);
3151 return (NULL);
3152 }
3153 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003154
Daniel Veillard4255d502002-04-16 15:50:10 +00003155 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003156 if (ctxt->assemble != NULL)
3157 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 return (ret);
3159}
3160
3161/**
3162 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003163 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003164 * @schema: the schema being built
3165 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003166 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003167 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003168 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003169 * *WARNING* this interface is highly subject to change
3170 *
3171 * Returns the new struture or NULL in case of error
3172 */
3173static xmlSchemaTypePtr
3174xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003175 const xmlChar * name, const xmlChar * namespace,
3176 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003177{
3178 xmlSchemaTypePtr ret = NULL;
3179 int val;
3180
3181 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3182 return (NULL);
3183
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003184#ifdef DEBUG
3185 fprintf(stderr, "Adding type %s\n", name);
3186 if (namespace != NULL)
3187 fprintf(stderr, " target namespace %s\n", namespace);
3188#endif
3189
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 if (schema->typeDecl == NULL)
3191 schema->typeDecl = xmlHashCreate(10);
3192 if (schema->typeDecl == NULL)
3193 return (NULL);
3194
3195 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3196 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003197 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003198 return (NULL);
3199 }
3200 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003201 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003202 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003203 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003204 if (val != 0) {
3205 if (ctxt->includes == 0) {
3206 xmlSchemaPCustomErr(ctxt,
3207 XML_SCHEMAP_REDEFINED_TYPE,
3208 NULL, NULL, node,
3209 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003210 xmlFree(ret);
3211 return (NULL);
3212 } else {
3213 xmlSchemaTypePtr prev;
3214
3215 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3216 if (prev == NULL) {
3217 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003218 XML_ERR_INTERNAL_ERROR,
3219 "Internal error: xmlSchemaAddType, on type "
3220 "'%s'.\n",
3221 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003222 xmlFree(ret);
3223 return (NULL);
3224 }
3225 ret->redef = prev->redef;
3226 prev->redef = ret;
3227 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003228 }
3229 ret->minOccurs = 1;
3230 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003231 ret->attributeUses = NULL;
3232 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003233 if (ctxt->assemble != NULL)
3234 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003235 return (ret);
3236}
3237
3238/**
3239 * xmlSchemaAddGroup:
3240 * @ctxt: a schema validation context
3241 * @schema: the schema being built
3242 * @name: the group name
3243 *
3244 * Add an XML schema Group definition
3245 *
3246 * Returns the new struture or NULL in case of error
3247 */
3248static xmlSchemaTypePtr
3249xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003250 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003251{
3252 xmlSchemaTypePtr ret = NULL;
3253 int val;
3254
3255 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3256 return (NULL);
3257
3258 if (schema->groupDecl == NULL)
3259 schema->groupDecl = xmlHashCreate(10);
3260 if (schema->groupDecl == NULL)
3261 return (NULL);
3262
3263 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3264 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003265 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003266 return (NULL);
3267 }
3268 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003269 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003270 val =
3271 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3272 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003273 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003274 xmlSchemaPCustomErr(ctxt,
3275 XML_SCHEMAP_REDEFINED_GROUP,
3276 NULL, NULL, node,
3277 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003278 xmlFree(ret);
3279 return (NULL);
3280 }
3281 ret->minOccurs = 1;
3282 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003283 if (ctxt->assemble != NULL)
3284 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003285 return (ret);
3286}
3287
Daniel Veillard3646d642004-06-02 19:19:14 +00003288/**
3289 * xmlSchemaNewWildcardNs:
3290 * @ctxt: a schema validation context
3291 *
3292 * Creates a new wildcard namespace constraint.
3293 *
3294 * Returns the new struture or NULL in case of error
3295 */
3296static xmlSchemaWildcardNsPtr
3297xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3298{
3299 xmlSchemaWildcardNsPtr ret;
3300
3301 ret = (xmlSchemaWildcardNsPtr)
3302 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3303 if (ret == NULL) {
3304 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3305 return (NULL);
3306 }
3307 ret->value = NULL;
3308 ret->next = NULL;
3309 return (ret);
3310}
3311
3312/**
3313 * xmlSchemaAddWildcard:
3314 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003315 * Adds a wildcard. It corresponds to a
3316 * xsd:anyAttribute and is used as storage for namespace
3317 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003318 *
3319 * Returns the new struture or NULL in case of error
3320 */
3321static xmlSchemaWildcardPtr
3322xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3323{
3324 xmlSchemaWildcardPtr ret = NULL;
3325
3326 if (ctxt == NULL)
3327 return (NULL);
3328
3329 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3330 if (ret == NULL) {
3331 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3332 return (NULL);
3333 }
3334 memset(ret, 0, sizeof(xmlSchemaWildcard));
3335 ret->minOccurs = 1;
3336 ret->maxOccurs = 1;
3337
3338 return (ret);
3339}
3340
Daniel Veillard4255d502002-04-16 15:50:10 +00003341/************************************************************************
3342 * *
3343 * Utilities for parsing *
3344 * *
3345 ************************************************************************/
3346
3347/**
3348 * xmlGetQNameProp:
3349 * @ctxt: a schema validation context
3350 * @node: a subtree containing XML Schema informations
3351 * @name: the attribute name
3352 * @namespace: the result namespace if any
3353 *
3354 * Extract a QName Attribute value
3355 *
3356 * Returns the NCName or NULL if not found, and also update @namespace
3357 * with the namespace URI
3358 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003359static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003360xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003361 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003362{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003363 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003364 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003365 const xmlChar *ret, *prefix;
3366 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003367 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003368
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003369 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003370 attr = xmlSchemaGetPropNode(node, name);
3371 if (attr == NULL)
3372 return (NULL);
3373 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003374
Daniel Veillard4255d502002-04-16 15:50:10 +00003375 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003376 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003377
Daniel Veillardba0153a2004-04-01 10:42:31 +00003378 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003379 ns = xmlSearchNs(node->doc, node, 0);
3380 if (ns) {
3381 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3382 return (val);
3383 }
3384 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003385 ret = xmlSplitQName3(val, &len);
3386 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003387 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003388 }
3389 ret = xmlDictLookup(ctxt->dict, ret, -1);
3390 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003391
3392 ns = xmlSearchNs(node->doc, node, prefix);
3393 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003394 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3395 NULL, NULL, (xmlNodePtr) attr,
3396 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003397 "The QName value '%s' has no corresponding namespace "
3398 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003400 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003401 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403}
3404
3405/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003406 * xmlSchemaPValAttrNodeQNameValue:
3407 * @ctxt: a schema parser context
3408 * @schema: the schema context
3409 * @ownerDes: the designation of the parent element
3410 * @ownerItem: the parent as a schema object
3411 * @value: the QName value
3412 * @local: the resulting local part if found, the attribute value otherwise
3413 * @uri: the resulting namespace URI if found
3414 *
3415 * Extracts the local name and the URI of a QName value and validates it.
3416 * This one is intended to be used on attribute values that
3417 * should resolve to schema components.
3418 *
3419 * Returns 0, in case the QName is valid, a positive error code
3420 * if not valid and -1 if an internal error occurs.
3421 */
3422static int
3423xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3424 xmlSchemaPtr schema,
3425 xmlChar **ownerDes,
3426 xmlSchemaTypePtr ownerItem,
3427 xmlAttrPtr attr,
3428 const xmlChar *value,
3429 const xmlChar **uri,
3430 const xmlChar **prefix,
3431 const xmlChar **local)
3432{
3433 const xmlChar *pref;
3434 xmlNsPtr ns;
3435 int len, ret;
3436
3437 *uri = NULL;
3438 *local = NULL;
3439 if (prefix != 0)
3440 *prefix = NULL;
3441 ret = xmlValidateQName(value, 1);
3442 if (ret > 0) {
3443 xmlSchemaPSimpleTypeErr(ctxt,
3444 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3445 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003446 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3447 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003448 NULL, NULL, NULL);
3449 *local = value;
3450 return (ctxt->err);
3451 } else if (ret < 0)
3452 return (-1);
3453
3454 if (!strchr((char *) value, ':')) {
3455 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3456 if (ns)
3457 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3458 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3459 /*
3460 * This one takes care of included schemas with no
3461 * target namespace.
3462 */
3463 *uri = schema->targetNamespace;
3464 }
3465 *local = value;
3466 return (0);
3467 }
3468 /*
3469 * At this point xmlSplitQName3 has to return a local name.
3470 */
3471 *local = xmlSplitQName3(value, &len);
3472 *local = xmlDictLookup(ctxt->dict, *local, -1);
3473 pref = xmlDictLookup(ctxt->dict, value, len);
3474 if (prefix != 0)
3475 *prefix = pref;
3476 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3477 if (ns == NULL) {
3478 xmlSchemaPSimpleTypeErr(ctxt,
3479 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3480 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003481 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3482 "The QName value '%s' has no corresponding namespace "
3483 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003484 return (ctxt->err);
3485 } else {
3486 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3487 }
3488 return (0);
3489}
3490
3491/**
3492 * xmlSchemaPValAttrNodeQName:
3493 * @ctxt: a schema parser context
3494 * @schema: the schema context
3495 * @ownerDes: the designation of the owner element
3496 * @ownerItem: the owner as a schema object
3497 * @attr: the attribute node
3498 * @local: the resulting local part if found, the attribute value otherwise
3499 * @uri: the resulting namespace URI if found
3500 *
3501 * Extracts and validates the QName of an attribute value.
3502 * This one is intended to be used on attribute values that
3503 * should resolve to schema components.
3504 *
3505 * Returns 0, in case the QName is valid, a positive error code
3506 * if not valid and -1 if an internal error occurs.
3507 */
3508static int
3509xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3510 xmlSchemaPtr schema,
3511 xmlChar **ownerDes,
3512 xmlSchemaTypePtr ownerItem,
3513 xmlAttrPtr attr,
3514 const xmlChar **uri,
3515 const xmlChar **prefix,
3516 const xmlChar **local)
3517{
3518 const xmlChar *value;
3519
3520 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3521 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3522 ownerDes, ownerItem, attr, value, uri, prefix, local));
3523}
3524
3525/**
3526 * xmlSchemaPValAttrQName:
3527 * @ctxt: a schema parser context
3528 * @schema: the schema context
3529 * @ownerDes: the designation of the parent element
3530 * @ownerItem: the owner as a schema object
3531 * @ownerElem: the parent node of the attribute
3532 * @name: the name of the attribute
3533 * @local: the resulting local part if found, the attribute value otherwise
3534 * @uri: the resulting namespace URI if found
3535 *
3536 * Extracts and validates the QName of an attribute value.
3537 *
3538 * Returns 0, in case the QName is valid, a positive error code
3539 * if not valid and -1 if an internal error occurs.
3540 */
3541static int
3542xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3543 xmlSchemaPtr schema,
3544 xmlChar **ownerDes,
3545 xmlSchemaTypePtr ownerItem,
3546 xmlNodePtr ownerElem,
3547 const char *name,
3548 const xmlChar **uri,
3549 const xmlChar **prefix,
3550 const xmlChar **local)
3551{
3552 xmlAttrPtr attr;
3553
3554 attr = xmlSchemaGetPropNode(ownerElem, name);
3555 if (attr == NULL) {
3556 *local = NULL;
3557 *uri = NULL;
3558 return (0);
3559 }
3560 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3561 ownerDes, ownerItem, attr, uri, prefix, local));
3562}
3563
3564/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003565 * xmlGetMaxOccurs:
3566 * @ctxt: a schema validation context
3567 * @node: a subtree containing XML Schema informations
3568 *
3569 * Get the maxOccurs property
3570 *
3571 * Returns the default if not found, or the value
3572 */
3573static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003574xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3575 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003576{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003577 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003578 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003579 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003580
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003581 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3582 if (attr == NULL)
3583 return (def);
3584 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003585
3586 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003587 if (max != UNBOUNDED) {
3588 xmlSchemaPSimpleTypeErr(ctxt,
3589 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3590 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3591 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3592 val, NULL, NULL, NULL);
3593 return (def);
3594 } else
3595 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003596 }
3597
3598 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003599 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003600 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003601 if (*cur == 0) {
3602 xmlSchemaPSimpleTypeErr(ctxt,
3603 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3604 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3605 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3606 val, NULL, NULL, NULL);
3607 return (def);
3608 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003610 ret = ret * 10 + (*cur - '0');
3611 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 }
William M. Brack76e95df2003-10-18 16:20:14 +00003613 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003614 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003615 /*
3616 * TODO: Restrict the maximal value to Integer.
3617 */
3618 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3619 xmlSchemaPSimpleTypeErr(ctxt,
3620 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3621 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3622 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3623 val, NULL, NULL, NULL);
3624 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003625 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003626 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003627}
3628
3629/**
3630 * xmlGetMinOccurs:
3631 * @ctxt: a schema validation context
3632 * @node: a subtree containing XML Schema informations
3633 *
3634 * Get the minOccurs property
3635 *
3636 * Returns the default if not found, or the value
3637 */
3638static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003639xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3640 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003642 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003643 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003644 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003645
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003646 attr = xmlSchemaGetPropNode(node, "minOccurs");
3647 if (attr == NULL)
3648 return (def);
3649 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003650 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003651 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003652 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003653 if (*cur == 0) {
3654 xmlSchemaPSimpleTypeErr(ctxt,
3655 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3656 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3657 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3658 val, NULL, NULL, NULL);
3659 return (def);
3660 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003661 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 ret = ret * 10 + (*cur - '0');
3663 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003664 }
William M. Brack76e95df2003-10-18 16:20:14 +00003665 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003666 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003667 /*
3668 * TODO: Restrict the maximal value to Integer.
3669 */
3670 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3671 xmlSchemaPSimpleTypeErr(ctxt,
3672 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3673 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3674 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3675 val, NULL, NULL, NULL);
3676 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003677 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003679}
3680
3681/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003682 * xmlSchemaPGetBoolNodeValue:
3683 * @ctxt: a schema validation context
3684 * @ownerDes: owner designation
3685 * @ownerItem: the owner as a schema item
3686 * @node: the node holding the value
3687 *
3688 * Converts a boolean string value into 1 or 0.
3689 *
3690 * Returns 0 or 1.
3691 */
3692static int
3693xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3694 xmlChar **ownerDes,
3695 xmlSchemaTypePtr ownerItem,
3696 xmlNodePtr node)
3697{
3698 xmlChar *value = NULL;
3699 int res = 0;
3700
3701 value = xmlNodeGetContent(node);
3702 /*
3703 * 3.2.2.1 Lexical representation
3704 * An instance of a datatype that is defined as ·boolean·
3705 * can have the following legal literals {true, false, 1, 0}.
3706 */
3707 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3708 res = 1;
3709 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3710 res = 0;
3711 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3712 res = 1;
3713 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3714 res = 0;
3715 else {
3716 xmlSchemaPSimpleTypeErr(ctxt,
3717 XML_SCHEMAP_INVALID_BOOLEAN,
3718 ownerDes, ownerItem, node,
3719 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3720 "(1 | 0 | true | false)", BAD_CAST value,
3721 NULL, NULL, NULL);
3722 }
3723 if (value != NULL)
3724 xmlFree(value);
3725 return (res);
3726}
3727
3728/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003729 * xmlGetBooleanProp:
3730 * @ctxt: a schema validation context
3731 * @node: a subtree containing XML Schema informations
3732 * @name: the attribute name
3733 * @def: the default value
3734 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003735 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003736 *
3737 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003738 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003739 */
3740static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003741xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3742 xmlChar **ownerDes,
3743 xmlSchemaTypePtr ownerItem,
3744 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003745 const char *name, int def)
3746{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003747 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003748
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003749 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003750 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003751 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003752 /*
3753 * 3.2.2.1 Lexical representation
3754 * An instance of a datatype that is defined as ·boolean·
3755 * can have the following legal literals {true, false, 1, 0}.
3756 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003757 if (xmlStrEqual(val, BAD_CAST "true"))
3758 def = 1;
3759 else if (xmlStrEqual(val, BAD_CAST "false"))
3760 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003761 else if (xmlStrEqual(val, BAD_CAST "1"))
3762 def = 1;
3763 else if (xmlStrEqual(val, BAD_CAST "0"))
3764 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003765 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003766 xmlSchemaPSimpleTypeErr(ctxt,
3767 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003768 ownerDes, ownerItem, node,
3769 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3770 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003771 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003772 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003773}
3774
3775/************************************************************************
3776 * *
3777 * Shema extraction from an Infoset *
3778 * *
3779 ************************************************************************/
3780static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3781 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003782 xmlNodePtr node,
3783 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003784static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3785 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003786 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003787 xmlNodePtr node,
3788 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003789static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3790 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003791 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003792 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003793static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3794 xmlSchemaPtr schema,
3795 xmlNodePtr node);
3796static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3797 xmlSchemaPtr schema,
3798 xmlNodePtr node);
3799static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3800 ctxt,
3801 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003802 xmlNodePtr node,
3803 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003804static xmlSchemaAttributeGroupPtr
3805xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003806 xmlSchemaPtr schema, xmlNodePtr node,
3807 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003808static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3809 xmlSchemaPtr schema,
3810 xmlNodePtr node);
3811static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3812 xmlSchemaPtr schema,
3813 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003814static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003815xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3816 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003817
3818/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003819 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003820 *
3821 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003822 * @ownerDes: the designation of the parent element
3823 * @ownerItem: the schema object owner if existent
3824 * @attr: the schema attribute node being validated
3825 * @value: the value
3826 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003827 *
3828 * Validates a value against the given built-in type.
3829 * This one is intended to be used internally for validation
3830 * of schema attribute values during parsing of the schema.
3831 *
3832 * Returns 0 if the value is valid, a positive error code
3833 * number otherwise and -1 in case of an internal or API error.
3834 */
3835static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003836xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3837 xmlChar **ownerDes,
3838 xmlSchemaTypePtr ownerItem,
3839 xmlAttrPtr attr,
3840 const xmlChar *value,
3841 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003842{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003843
Daniel Veillardc0826a72004-08-10 14:17:33 +00003844 int ret = 0;
3845
3846 /*
3847 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3848 * one is really meant to be used internally, so better not.
3849 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003850 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003851 return (-1);
3852 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3853 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003854 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003855 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003856 "type '%s' is not a built-in type.\n",
3857 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003858 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003859 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003860 switch (type->builtInType) {
3861 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003862 case XML_SCHEMAS_QNAME:
3863 case XML_SCHEMAS_ANYURI:
3864 case XML_SCHEMAS_TOKEN:
3865 case XML_SCHEMAS_LANGUAGE:
3866 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
3867 break;
3868
3869 /*
3870 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003871 ret = xmlValidateNCName(value, 1);
3872 break;
3873 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003874 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003875 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003876 "Internal error: xmlSchemaPvalueAttrNode, use "
3877 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3878 "for extracting QName valueues instead.\n",
3879 NULL, NULL);
3880 return (-1);
3881 case XML_SCHEMAS_ANYURI:
3882 if (value != NULL) {
3883 xmlURIPtr uri = xmlParseURI((const char *) value);
3884 if (uri == NULL)
3885 ret = 1;
3886 else
3887 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003888 }
3889 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003890 case XML_SCHEMAS_TOKEN: {
3891 const xmlChar *cur = value;
3892
3893 if (IS_BLANK_CH(*cur)) {
3894 ret = 1;
3895 } else while (*cur != 0) {
3896 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3897 ret = 1;
3898 break;
3899 } else if (*cur == ' ') {
3900 cur++;
3901 if ((*cur == 0) || (*cur == ' ')) {
3902 ret = 1;
3903 break;
3904 }
3905 } else {
3906 cur++;
3907 }
3908 }
3909 }
3910 break;
3911 case XML_SCHEMAS_LANGUAGE:
3912 if (xmlCheckLanguageID(value) != 1)
3913 ret = 1;
3914 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003915 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003916 default: {
3917 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003918 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003919 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003920 "valueidation using the type '%s' is not implemented "
3921 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003922 type->name, NULL);
3923 return (-1);
3924 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003925 }
3926 /*
3927 * TODO: Should we use the S4S error codes instead?
3928 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003929 if (ret < 0) {
3930 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3931 XML_SCHEMAP_INTERNAL,
3932 "Internal error: xmlSchemaPValAttrNodeValue, "
3933 "failed to validate a schema attribute value.\n",
3934 NULL, NULL);
3935 return (-1);
3936 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003937 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3938 xmlSchemaPSimpleTypeErr(ctxt,
3939 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3940 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003942 NULL, NULL, NULL);
3943 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3944 } else {
3945 xmlSchemaPSimpleTypeErr(ctxt,
3946 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3947 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003948 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003949 NULL, NULL, NULL);
3950 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3951 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003952 }
3953 return (ret);
3954}
3955
3956/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003957 * xmlSchemaPValAttrNode:
3958 *
3959 * @ctxt: a schema parser context
3960 * @ownerDes: the designation of the parent element
3961 * @ownerItem: the schema object owner if existent
3962 * @attr: the schema attribute node being validated
3963 * @type: the built-in type to be validated against
3964 * @value: the resulting value if any
3965 *
3966 * Extracts and validates a value against the given built-in type.
3967 * This one is intended to be used internally for validation
3968 * of schema attribute values during parsing of the schema.
3969 *
3970 * Returns 0 if the value is valid, a positive error code
3971 * number otherwise and -1 in case of an internal or API error.
3972 */
3973static int
3974xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3975 xmlChar **ownerDes,
3976 xmlSchemaTypePtr ownerItem,
3977 xmlAttrPtr attr,
3978 xmlSchemaTypePtr type,
3979 const xmlChar **value)
3980{
3981 const xmlChar *val;
3982
3983 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3984 return (-1);
3985
3986 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3987 if (value != NULL)
3988 *value = val;
3989
3990 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3991 val, type));
3992}
3993
3994/**
3995 * xmlSchemaPValAttr:
3996 *
3997 * @ctxt: a schema parser context
3998 * @node: the element node of the attribute
3999 * @ownerDes: the designation of the parent element
4000 * @ownerItem: the schema object owner if existent
4001 * @ownerElem: the owner element node
4002 * @name: the name of the schema attribute node
4003 * @type: the built-in type to be validated against
4004 * @value: the resulting value if any
4005 *
4006 * Extracts and validates a value against the given built-in type.
4007 * This one is intended to be used internally for validation
4008 * of schema attribute values during parsing of the schema.
4009 *
4010 * Returns 0 if the value is valid, a positive error code
4011 * number otherwise and -1 in case of an internal or API error.
4012 */
4013static int
4014xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4015 xmlChar **ownerDes,
4016 xmlSchemaTypePtr ownerItem,
4017 xmlNodePtr ownerElem,
4018 const char *name,
4019 xmlSchemaTypePtr type,
4020 const xmlChar **value)
4021{
4022 xmlAttrPtr attr;
4023
4024 if ((ctxt == NULL) || (type == NULL)) {
4025 if (value != NULL)
4026 *value = NULL;
4027 return (-1);
4028 }
4029 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4030 if (value != NULL)
4031 *value = NULL;
4032 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004033 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004034 "Internal error: xmlSchemaPValAttr, the given "
4035 "type '%s' is not a built-in type.\n",
4036 type->name, NULL);
4037 return (-1);
4038 }
4039 attr = xmlSchemaGetPropNode(ownerElem, name);
4040 if (attr == NULL) {
4041 if (value != NULL)
4042 *value = NULL;
4043 return (0);
4044 }
4045 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4046 type, value));
4047}
4048/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004049 * xmlSchemaParseAttrDecls:
4050 * @ctxt: a schema validation context
4051 * @schema: the schema being built
4052 * @node: a subtree containing XML Schema informations
4053 * @type: the hosting type
4054 *
4055 * parse a XML schema attrDecls declaration corresponding to
4056 * <!ENTITY % attrDecls
4057 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4058 */
4059static xmlNodePtr
4060xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4061 xmlNodePtr child, xmlSchemaTypePtr type)
4062{
4063 xmlSchemaAttributePtr lastattr, attr;
4064
4065 lastattr = NULL;
4066 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004067 (IS_SCHEMA(child, "attributeGroup"))) {
4068 attr = NULL;
4069 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004070 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004071 } else if (IS_SCHEMA(child, "attributeGroup")) {
4072 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004073 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004074 }
4075 if (attr != NULL) {
4076 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004077 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4078 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4079 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004080 type->attributes = attr;
4081 lastattr = attr;
4082 } else {
4083 lastattr->next = attr;
4084 lastattr = attr;
4085 }
4086 }
4087 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004088 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004089 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004090}
4091
4092/**
4093 * xmlSchemaParseAnnotation:
4094 * @ctxt: a schema validation context
4095 * @schema: the schema being built
4096 * @node: a subtree containing XML Schema informations
4097 *
4098 * parse a XML schema Attrribute declaration
4099 * *WARNING* this interface is highly subject to change
4100 *
William M. Bracke7091952004-05-11 15:09:58 +00004101 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004102 * 1 in case of success.
4103 */
4104static xmlSchemaAnnotPtr
4105xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4106 xmlNodePtr node)
4107{
4108 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004109 xmlNodePtr child = NULL;
4110 xmlAttrPtr attr;
4111 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004112
Daniel Veillardc0826a72004-08-10 14:17:33 +00004113 /*
4114 * INFO: S4S completed.
4115 */
4116 /*
4117 * id = ID
4118 * {any attributes with non-schema namespace . . .}>
4119 * Content: (appinfo | documentation)*
4120 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004121 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4122 return (NULL);
4123 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004124 attr = node->properties;
4125 while (attr != NULL) {
4126 if (((attr->ns == NULL) &&
4127 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4128 ((attr->ns != NULL) &&
4129 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4130
4131 xmlSchemaPIllegalAttrErr(ctxt,
4132 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4133 NULL, NULL, attr);
4134 }
4135 attr = attr->next;
4136 }
4137 /* TODO: Check id. */
4138
4139 /*
4140 * And now for the children...
4141 */
4142 child = node->children;
4143 while (child != NULL) {
4144 if (IS_SCHEMA(child, "appinfo")) {
4145 /* TODO: make available the content of "appinfo". */
4146 /*
4147 * source = anyURI
4148 * {any attributes with non-schema namespace . . .}>
4149 * Content: ({any})*
4150 */
4151 attr = child->properties;
4152 while (attr != NULL) {
4153 if (((attr->ns == NULL) &&
4154 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4155 ((attr->ns != NULL) &&
4156 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004157
Daniel Veillardc0826a72004-08-10 14:17:33 +00004158 xmlSchemaPIllegalAttrErr(ctxt,
4159 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4160 NULL, NULL, attr);
4161 }
4162 attr = attr->next;
4163 }
4164 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4165 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4166 child = child->next;
4167 } else if (IS_SCHEMA(child, "documentation")) {
4168 /* TODO: make available the content of "documentation". */
4169 /*
4170 * source = anyURI
4171 * {any attributes with non-schema namespace . . .}>
4172 * Content: ({any})*
4173 */
4174 attr = child->properties;
4175 while (attr != NULL) {
4176 if (attr->ns == NULL) {
4177 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4178 xmlSchemaPIllegalAttrErr(ctxt,
4179 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4180 NULL, NULL, attr);
4181 }
4182 } else {
4183 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4184 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4185 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4186
4187 xmlSchemaPIllegalAttrErr(ctxt,
4188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4189 NULL, NULL, attr);
4190 }
4191 }
4192 attr = attr->next;
4193 }
4194 /*
4195 * Attribute "xml:lang".
4196 */
4197 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4198 if (attr != NULL)
4199 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4200 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4201 child = child->next;
4202 } else {
4203 if (!barked)
4204 xmlSchemaPContentErr(ctxt,
4205 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4206 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4207 barked = 1;
4208 child = child->next;
4209 }
4210 }
4211
Daniel Veillard4255d502002-04-16 15:50:10 +00004212 return (ret);
4213}
4214
4215/**
4216 * xmlSchemaParseFacet:
4217 * @ctxt: a schema validation context
4218 * @schema: the schema being built
4219 * @node: a subtree containing XML Schema informations
4220 *
4221 * parse a XML schema Facet declaration
4222 * *WARNING* this interface is highly subject to change
4223 *
4224 * Returns the new type structure or NULL in case of error
4225 */
4226static xmlSchemaFacetPtr
4227xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004228 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004229{
4230 xmlSchemaFacetPtr facet;
4231 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004232 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004233
4234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4235 return (NULL);
4236
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004237 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004238 if (facet == NULL) {
4239 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4240 return (NULL);
4241 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004242 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004243 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004244 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004245 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4246 "Facet %s has no value\n", node->name, NULL);
4247 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 return (NULL);
4249 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004250 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004251 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004252 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004253 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004254 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004255 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004256 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004257 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004258 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004259 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004260 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004261 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004262 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004265 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004266 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004267 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004268 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004270 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004271 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4272 } else if (IS_SCHEMA(node, "minLength")) {
4273 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4274 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004275 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4276 "Unknown facet type %s\n", node->name, NULL);
4277 xmlSchemaFreeFacet(facet);
4278 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004279 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004280 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004281 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004282 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4283 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4284 const xmlChar *fixed;
4285
4286 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4287 if (fixed != NULL) {
4288 if (xmlStrEqual(fixed, BAD_CAST "true"))
4289 facet->fixed = 1;
4290 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004291 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004292 child = node->children;
4293
4294 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004295 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4296 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 }
4298 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004299 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4300 "Facet %s has unexpected child content\n",
4301 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004302 }
4303 return (facet);
4304}
4305
4306/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004307 * xmlSchemaParseWildcardNs:
4308 * @ctxt: a schema parser context
4309 * @wildc: the wildcard, already created
4310 * @node: a subtree containing XML Schema informations
4311 *
4312 * Parses the attribute "processContents" and "namespace"
4313 * of a xsd:anyAttribute and xsd:any.
4314 * *WARNING* this interface is highly subject to change
4315 *
4316 * Returns 0 if everything goes fine, a positive error code
4317 * if something is not valid and -1 if an internal error occurs.
4318 */
4319static int
4320xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4321 xmlSchemaPtr schema,
4322 xmlSchemaWildcardPtr wildc,
4323 xmlNodePtr node)
4324{
4325 const xmlChar *pc, *ns, *dictnsItem;
4326 int ret = 0;
4327 xmlChar *nsItem;
4328 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4329 xmlAttrPtr attr;
4330
4331 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4332 if ((pc == NULL)
4333 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4334 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4335 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4336 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4337 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4338 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4339 } else {
4340 xmlSchemaPSimpleTypeErr(ctxt,
4341 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4342 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004343 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004344 NULL, NULL, NULL);
4345 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4346 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4347 }
4348 /*
4349 * Build the namespace constraints.
4350 */
4351 attr = xmlSchemaGetPropNode(node, "namespace");
4352 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4353 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4354 wildc->any = 1;
4355 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4356 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4357 if (wildc->negNsSet == NULL) {
4358 return (-1);
4359 }
4360 wildc->negNsSet->value = schema->targetNamespace;
4361 } else {
4362 const xmlChar *end, *cur;
4363
4364 cur = ns;
4365 do {
4366 while (IS_BLANK_CH(*cur))
4367 cur++;
4368 end = cur;
4369 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4370 end++;
4371 if (end == cur)
4372 break;
4373 nsItem = xmlStrndup(cur, end - cur);
4374 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4375 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4376 xmlSchemaPSimpleTypeErr(ctxt,
4377 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4378 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004379 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004380 "((##any | ##other) | List of (anyURI | "
4381 "(##targetNamespace | ##local)))",
4382 nsItem, NULL, NULL, NULL);
4383 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4384 } else {
4385 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4386 dictnsItem = schema->targetNamespace;
4387 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4388 dictnsItem = NULL;
4389 } else {
4390 /*
4391 * Validate the item (anyURI).
4392 */
4393 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4394 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4395 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4396 }
4397 /*
4398 * Avoid dublicate namespaces.
4399 */
4400 tmp = wildc->nsSet;
4401 while (tmp != NULL) {
4402 if (dictnsItem == tmp->value)
4403 break;
4404 tmp = tmp->next;
4405 }
4406 if (tmp == NULL) {
4407 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4408 if (tmp == NULL) {
4409 xmlFree(nsItem);
4410 return (-1);
4411 }
4412 tmp->value = dictnsItem;
4413 tmp->next = NULL;
4414 if (wildc->nsSet == NULL)
4415 wildc->nsSet = tmp;
4416 else
4417 lastNs->next = tmp;
4418 lastNs = tmp;
4419 }
4420
4421 }
4422 xmlFree(nsItem);
4423 cur = end;
4424 } while (*cur != 0);
4425 }
4426 return (ret);
4427}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004428
4429static int
4430xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4431 xmlSchemaTypePtr item,
4432 xmlNodePtr node,
4433 int minOccurs,
4434 int maxOccurs) {
4435
4436 if (maxOccurs != UNBOUNDED) {
4437 /*
4438 * TODO: Maby we should better not create the particle,
4439 * if min/max is invalid, since it could confuse the build of the
4440 * content model.
4441 */
4442 /*
4443 * 3.9.6 Schema Component Constraint: Particle Correct
4444 *
4445 */
4446 if (maxOccurs < 1) {
4447 /*
4448 * 2.2 {max occurs} must be greater than or equal to 1.
4449 */
4450 xmlSchemaPCustomAttrErr(ctxt,
4451 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4452 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4453 "The value must be greater than or equal to 1");
4454 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4455 } else if (minOccurs > maxOccurs) {
4456 /*
4457 * 2.1 {min occurs} must not be greater than {max occurs}.
4458 */
4459 xmlSchemaPCustomAttrErr(ctxt,
4460 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4461 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4462 "The value must not be greater than the value of 'maxOccurs'");
4463 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4464 }
4465 }
4466 return (0);
4467}
4468
Daniel Veillardc0826a72004-08-10 14:17:33 +00004469/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 * xmlSchemaParseAny:
4471 * @ctxt: a schema validation context
4472 * @schema: the schema being built
4473 * @node: a subtree containing XML Schema informations
4474 *
4475 * parse a XML schema Any declaration
4476 * *WARNING* this interface is highly subject to change
4477 *
4478 * Returns the new type structure or NULL in case of error
4479 */
4480static xmlSchemaTypePtr
4481xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4482 xmlNodePtr node)
4483{
4484 xmlSchemaTypePtr type;
4485 xmlNodePtr child = NULL;
4486 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004487 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004488 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004489
4490 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4491 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004492 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4493 "(nonNegativeInteger | unbounded)");
4494 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4495 "nonNegativeInteger");
4496 if ((minOccurs == 0) && (maxOccurs == 0))
4497 return (NULL);
4498
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004499 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004500 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004501 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004502 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004503 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004504 type->type = XML_SCHEMA_TYPE_ANY;
4505
Daniel Veillardc0826a72004-08-10 14:17:33 +00004506 wildc = xmlSchemaAddWildcard(ctxt);
4507 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004508 * Check min/max sanity.
4509 */
4510 type->maxOccurs = maxOccurs;
4511 type->minOccurs = minOccurs;
4512 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4513 node, type->minOccurs, type->maxOccurs);
4514 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004515 * This is not nice, since it is won't be used as a attribute wildcard,
4516 * but better than adding a field to the structure.
4517 */
4518 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004519 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004520 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004521 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004522 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4523 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004524 }
4525 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004526 xmlSchemaPErr2(ctxt, node, child,
4527 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4528 "Sequence %s has unexpected content\n", type->name,
4529 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004530 }
4531
4532 return (type);
4533}
4534
4535/**
4536 * xmlSchemaParseNotation:
4537 * @ctxt: a schema validation context
4538 * @schema: the schema being built
4539 * @node: a subtree containing XML Schema informations
4540 *
4541 * parse a XML schema Notation declaration
4542 *
4543 * Returns the new structure or NULL in case of error
4544 */
4545static xmlSchemaNotationPtr
4546xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004547 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004548{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004549 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 xmlSchemaNotationPtr ret;
4551 xmlNodePtr child = NULL;
4552
4553 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4554 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004555 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004556 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004557 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4558 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004559 return (NULL);
4560 }
4561 ret = xmlSchemaAddNotation(ctxt, schema, name);
4562 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004563 return (NULL);
4564 }
4565 child = node->children;
4566 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004567 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4568 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004569 }
4570 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004571 xmlSchemaPErr2(ctxt, node, child,
4572 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4573 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 }
4575
4576 return (ret);
4577}
4578
4579/**
4580 * xmlSchemaParseAnyAttribute:
4581 * @ctxt: a schema validation context
4582 * @schema: the schema being built
4583 * @node: a subtree containing XML Schema informations
4584 *
4585 * parse a XML schema AnyAttrribute declaration
4586 * *WARNING* this interface is highly subject to change
4587 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004588 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004589 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004590static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004591xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4592 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004593{
Daniel Veillard3646d642004-06-02 19:19:14 +00004594 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004595 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004596 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004597
4598 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4599 return (NULL);
4600
Daniel Veillard3646d642004-06-02 19:19:14 +00004601 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004602 if (ret == NULL) {
4603 return (NULL);
4604 }
William M. Bracke7091952004-05-11 15:09:58 +00004605 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004606 /*
4607 * Check for illegal attributes.
4608 */
4609 attr = node->properties;
4610 while (attr != NULL) {
4611 if (attr->ns == NULL) {
4612 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4613 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4614 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4615 xmlSchemaPIllegalAttrErr(ctxt,
4616 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4617 NULL, NULL, attr);
4618 }
4619 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4620 xmlSchemaPIllegalAttrErr(ctxt,
4621 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4622 NULL, NULL, attr);
4623 }
4624 attr = attr->next;
4625 }
4626 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4627 /*
4628 * Parse the namespace list.
4629 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004630 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4631 xmlSchemaFreeWildcard(ret);
4632 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004633 }
4634 /*
4635 * And now for the children...
4636 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004637 child = node->children;
4638 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004639 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4640 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004641 }
4642 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004643 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004644 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4645 NULL, NULL, node, child,
4646 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004647 }
4648
4649 return (ret);
4650}
4651
4652
4653/**
4654 * xmlSchemaParseAttribute:
4655 * @ctxt: a schema validation context
4656 * @schema: the schema being built
4657 * @node: a subtree containing XML Schema informations
4658 *
4659 * parse a XML schema Attrribute declaration
4660 * *WARNING* this interface is highly subject to change
4661 *
William M. Bracke7091952004-05-11 15:09:58 +00004662 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004663 */
4664static xmlSchemaAttributePtr
4665xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004666 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004667{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004668 const xmlChar *name, *attrValue;
4669 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004670 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004671 xmlNodePtr child = NULL;
4672 xmlAttrPtr attr, nameAttr;
4673 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004674
4675 /*
4676 * Note that the w3c spec assumes the schema to be validated with schema
4677 * for schemas beforehand.
4678 *
4679 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004680 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004681
4682 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004684 attr = xmlSchemaGetPropNode(node, "ref");
4685 nameAttr = xmlSchemaGetPropNode(node, "name");
4686
4687 if ((attr == NULL) && (nameAttr == NULL)) {
4688 /*
4689 * 3.2.3 : 3.1
4690 * One of ref or name must be present, but not both
4691 */
4692 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4693 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4694 "One of the attributes 'ref' or 'name' must be present");
4695 return (NULL);
4696 }
4697 if ((topLevel) || (attr == NULL)) {
4698 if (nameAttr == NULL) {
4699 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4700 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4701 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004702 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004703 }
4704 } else
4705 isRef = 1;
4706
4707 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004708 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004709 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4710
4711 /*
4712 * Parse as attribute reference.
4713 */
4714 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4715 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4716 &refPrefix, &ref) != 0) {
4717 return (NULL);
4718 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004719 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004720 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004721 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004722 if (ret == NULL) {
4723 if (repName != NULL)
4724 xmlFree(repName);
4725 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004726 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004727 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4728 ret->node = node;
4729 ret->refNs = refNs;
4730 ret->refPrefix = refPrefix;
4731 ret->ref = ref;
4732 /*
4733 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4734 */
4735 if (nameAttr != NULL)
4736 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4737 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4738 "ref", "name");
4739 /*
4740 * Check for illegal attributes.
4741 */
4742 attr = node->properties;
4743 while (attr != NULL) {
4744 if (attr->ns == NULL) {
4745 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4746 xmlStrEqual(attr->name, BAD_CAST "form")) {
4747 /*
4748 * 3.2.3 : 3.2
4749 * If ref is present, then all of <simpleType>,
4750 * form and type must be absent.
4751 */
4752 xmlSchemaPIllegalAttrErr(ctxt,
4753 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4754 (xmlSchemaTypePtr) ret, attr);
4755 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4756 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4757 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4758 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4759 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4760 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4761 xmlSchemaPIllegalAttrErr(ctxt,
4762 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4763 &repName, (xmlSchemaTypePtr) ret, attr);
4764 }
4765 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4766 xmlSchemaPIllegalAttrErr(ctxt,
4767 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4768 &repName, (xmlSchemaTypePtr) ret, attr);
4769 }
4770 attr = attr->next;
4771 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004772 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004773 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004774
4775 /*
4776 * Parse as attribute declaration.
4777 */
4778 if (xmlSchemaPValAttrNode(ctxt,
4779 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4780 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4781 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004782 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004783 /*
4784 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4785 */
4786 /*
4787 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4788 */
4789 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4790 xmlSchemaPSimpleTypeErr(ctxt,
4791 XML_SCHEMAP_NO_XMLNS,
4792 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004793 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004794 "The value must not match 'xmlns'",
4795 NULL, NULL);
4796 if (repName != NULL)
4797 xmlFree(repName);
4798 return (NULL);
4799 }
4800 /*
4801 * Evaluate the target namespace
4802 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004803 if (topLevel) {
4804 ns = schema->targetNamespace;
4805 } else {
4806 attr = xmlSchemaGetPropNode(node, "form");
4807 if (attr != NULL) {
4808 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4809 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4810 ns = schema->targetNamespace;
4811 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4812 xmlSchemaPSimpleTypeErr(ctxt,
4813 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4814 &repName, NULL, (xmlNodePtr) attr,
4815 NULL, "(qualified | unqualified)",
4816 attrValue, NULL, NULL, NULL);
4817 }
4818 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4819 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004820 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004821 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004822 if (ret == NULL) {
4823 if (repName != NULL)
4824 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004825 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004826 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004827 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4828 ret->node = node;
4829 if (topLevel)
4830 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4831 /*
4832 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4833 */
4834 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4835 xmlSchemaPCustomErr(ctxt,
4836 XML_SCHEMAP_NO_XSI,
4837 &repName, (xmlSchemaTypePtr) ret, node,
4838 "The target namespace must not match '%s'",
4839 xmlSchemaInstanceNs);
4840 }
4841 /*
4842 * Check for illegal attributes.
4843 */
4844 attr = node->properties;
4845 while (attr != NULL) {
4846 if (attr->ns == NULL) {
4847 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4848 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4849 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4850 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4851 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4852 if ((topLevel) ||
4853 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4854 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4855 xmlSchemaPIllegalAttrErr(ctxt,
4856 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4857 &repName, (xmlSchemaTypePtr) ret, attr);
4858 }
4859 }
4860 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4861 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4862 &repName, (xmlSchemaTypePtr) ret, attr);
4863 }
4864 attr = attr->next;
4865 }
4866 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4867 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004868 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004869 /* TODO: Check ID. */
4870 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004871 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004872 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004873 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004874 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4875 if (ret->defValue != NULL)
4876 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4877 /*
4878 * Attribute "default".
4879 */
4880 attr = xmlSchemaGetPropNode(node, "default");
4881 if (attr != NULL) {
4882 /*
4883 * 3.2.3 : 1
4884 * default and fixed must not both be present.
4885 */
4886 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4887 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4888 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4889 } else
4890 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4891 }
4892 if (topLevel == 0) {
4893 /*
4894 * Attribute "use".
4895 */
4896 attr = xmlSchemaGetPropNode(node, "use");
4897 if (attr != NULL) {
4898 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4899 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4900 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4901 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4902 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4903 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4904 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4905 else
4906 xmlSchemaPSimpleTypeErr(ctxt,
4907 XML_SCHEMAP_INVALID_ATTR_USE,
4908 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004909 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004910 attrValue, NULL, NULL, NULL);
4911 } else
4912 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4913 /*
4914 * 3.2.3 : 2
4915 * If default and use are both present, use must have
4916 * the actual value optional.
4917 */
4918 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4919 (ret->defValue != NULL) &&
4920 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4921 xmlSchemaPSimpleTypeErr(ctxt,
4922 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4923 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004924 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004925 "The value must be 'optional' if the attribute "
4926 "'default' is present as well", NULL, NULL);
4927 }
4928 }
4929 /*
4930 * And now for the children...
4931 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004932 child = node->children;
4933 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004934 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4935 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004936 }
4937 if (isRef) {
4938 if (child != NULL) {
4939 if (IS_SCHEMA(child, "simpleType"))
4940 /*
4941 * 3.2.3 : 3.2
4942 * If ref is present, then all of <simpleType>,
4943 * form and type must be absent.
4944 */
4945 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4946 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4947 "(annotation?)");
4948 else
4949 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4950 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4951 "(annotation?)");
4952 }
4953 } else {
4954 if (IS_SCHEMA(child, "simpleType")) {
4955 if (ret->typeName != NULL) {
4956 /*
4957 * 3.2.3 : 4
4958 * type and <simpleType> must not both be present.
4959 */
4960 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4961 &repName, (xmlSchemaTypePtr) ret, node, child,
4962 "The attribute 'type' and the <simpleType> child "
4963 "are mutually exclusive", NULL);
4964 } else
4965 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4966 child = child->next;
4967 }
4968 if (child != NULL)
4969 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4970 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4971 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004972 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004973 /*
4974 * Cleanup.
4975 */
4976 if (repName != NULL)
4977 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004978 return (ret);
4979}
4980
4981/**
4982 * xmlSchemaParseAttributeGroup:
4983 * @ctxt: a schema validation context
4984 * @schema: the schema being built
4985 * @node: a subtree containing XML Schema informations
4986 *
4987 * parse a XML schema Attribute Group declaration
4988 * *WARNING* this interface is highly subject to change
4989 *
4990 * Returns the attribute group or NULL in case of error.
4991 */
4992static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004993xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004994 xmlSchemaPtr schema, xmlNodePtr node,
4995 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004996{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004997 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004998 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004999 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005000 const xmlChar *oldcontainer;
5001 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005002
5003 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5004 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005005
5006 nameAttr = xmlSchemaGetPropNode(node, "name");
5007 attr = xmlSchemaGetPropNode(node, "ref");
5008 if ((topLevel) || (attr == NULL)) {
5009 /*
5010 * Parse as an attribute group definition.
5011 * Note that those are allowed at top level only.
5012 */
5013 if (nameAttr == NULL) {
5014 xmlSchemaPMissingAttrErr(ctxt,
5015 XML_SCHEMAP_S4S_ATTR_MISSING,
5016 NULL, NULL, node, "name", NULL);
5017 return (NULL);
5018 }
5019 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5020 /*
5021 * The name is crucial, exit if invalid.
5022 */
5023 if (xmlSchemaPValAttrNode(ctxt,
5024 NULL, NULL, nameAttr,
5025 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5026 return (NULL);
5027 }
5028 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5029 if (ret == NULL)
5030 return (NULL);
5031 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5032 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5033 ret->node = node;
5034 } else {
5035 char buf[50];
5036 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5037
5038 /*
5039 * Parse as an attribute group definition reference.
5040 */
5041 if (attr == NULL) {
5042 xmlSchemaPMissingAttrErr(ctxt,
5043 XML_SCHEMAP_S4S_ATTR_MISSING,
5044 NULL, NULL, node, "ref", NULL);
5045 }
5046 xmlSchemaPValAttrNodeQName(ctxt, schema,
5047 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5048
5049 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5050 name = (const xmlChar *) buf;
5051 if (name == NULL) {
5052 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5053 "attribute group definition reference", node);
5054 return (NULL);
5055 }
5056 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5057 if (ret == NULL)
5058 return (NULL);
5059 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5060 ret->ref = ref;
5061 ret->refNs = refNs;
5062 /* TODO: Is @refPrefix currently used? */
5063 ret->refPrefix = refPrefix;
5064 ret->node = node;
5065 }
5066 /*
5067 * Check for illegal attributes.
5068 */
5069 attr = node->properties;
5070 while (attr != NULL) {
5071 if (attr->ns == NULL) {
5072 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5073 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5074 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5075 {
5076 xmlSchemaPIllegalAttrErr(ctxt,
5077 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5078 NULL, NULL, attr);
5079 }
5080 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5081 xmlSchemaPIllegalAttrErr(ctxt,
5082 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5083 NULL, NULL, attr);
5084 }
5085 attr = attr->next;
5086 }
5087 /* TODO: Validate "id" ? */
5088 /*
5089 * And now for the children...
5090 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005091 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005092 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005093 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005094 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005095 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5096 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005097 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005098 if (topLevel) {
5099 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5100 if (IS_SCHEMA(child, "anyAttribute")) {
5101 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5102 child = child->next;
5103 }
5104 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005105 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005106 xmlSchemaPContentErr(ctxt,
5107 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5108 NULL, NULL, node, child, NULL,
5109 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005110 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005111 ctxt->container = oldcontainer;
5112 return (ret);
5113}
5114
5115/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005116 * xmlSchemaPValAttrFormDefault:
5117 * @value: the value
5118 * @flags: the flags to be modified
5119 * @flagQualified: the specific flag for "qualified"
5120 *
5121 * Returns 0 if the value is valid, 1 otherwise.
5122 */
5123static int
5124xmlSchemaPValAttrFormDefault(const xmlChar *value,
5125 int *flags,
5126 int flagQualified)
5127{
5128 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5129 if ((*flags & flagQualified) == 0)
5130 *flags |= flagQualified;
5131 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5132 return (1);
5133
5134 return (0);
5135}
5136
5137/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005138 * xmlSchemaPValAttrBlockFinal:
5139 * @value: the value
5140 * @flags: the flags to be modified
5141 * @flagAll: the specific flag for "#all"
5142 * @flagExtension: the specific flag for "extension"
5143 * @flagRestriction: the specific flag for "restriction"
5144 * @flagSubstitution: the specific flag for "substitution"
5145 * @flagList: the specific flag for "list"
5146 * @flagUnion: the specific flag for "union"
5147 *
5148 * Validates the value of the attribute "final" and "block". The value
5149 * is converted into the specified flag values and returned in @flags.
5150 *
5151 * Returns 0 if the value is valid, 1 otherwise.
5152 */
5153
5154static int
5155xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5156 int *flags,
5157 int flagAll,
5158 int flagExtension,
5159 int flagRestriction,
5160 int flagSubstitution,
5161 int flagList,
5162 int flagUnion)
5163{
5164 int ret = 0;
5165
5166 /*
5167 * TODO: This does not check for dublicate entries.
5168 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005169 if (value == NULL)
5170 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005171 if (xmlStrEqual(value, BAD_CAST "#all")) {
5172 if (flagAll != -1)
5173 *flags |= flagAll;
5174 else {
5175 if (flagExtension != -1)
5176 *flags |= flagExtension;
5177 if (flagRestriction != -1)
5178 *flags |= flagRestriction;
5179 if (flagSubstitution != -1)
5180 *flags |= flagSubstitution;
5181 if (flagList != -1)
5182 *flags |= flagList;
5183 if (flagUnion != -1)
5184 *flags |= flagUnion;
5185 }
5186 } else {
5187 const xmlChar *end, *cur = value;
5188 xmlChar *item;
5189
5190 do {
5191 while (IS_BLANK_CH(*cur))
5192 cur++;
5193 end = cur;
5194 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5195 end++;
5196 if (end == cur)
5197 break;
5198 item = xmlStrndup(cur, end - cur);
5199 if (xmlStrEqual(item, BAD_CAST "extension")) {
5200 if (flagExtension != -1) {
5201 if ((*flags & flagExtension) == 0)
5202 *flags |= flagExtension;
5203 } else
5204 ret = 1;
5205 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5206 if (flagRestriction != -1) {
5207 if ((*flags & flagRestriction) == 0)
5208 *flags |= flagRestriction;
5209 } else
5210 ret = 1;
5211 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5212 if (flagSubstitution != -1) {
5213 if ((*flags & flagSubstitution) == 0)
5214 *flags |= flagSubstitution;
5215 } else
5216 ret = 1;
5217 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5218 if (flagList != -1) {
5219 if ((*flags & flagList) == 0)
5220 *flags |= flagList;
5221 } else
5222 ret = 1;
5223 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5224 if (flagUnion != -1) {
5225 if ((*flags & flagUnion) == 0)
5226 *flags |= flagUnion;
5227 } else
5228 ret = 1;
5229 } else
5230 ret = 1;
5231 if (item != NULL)
5232 xmlFree(item);
5233 cur = end;
5234 } while ((ret == 0) && (*cur != 0));
5235 }
5236
5237 return (ret);
5238}
5239
5240/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 * xmlSchemaParseElement:
5242 * @ctxt: a schema validation context
5243 * @schema: the schema being built
5244 * @node: a subtree containing XML Schema informations
5245 *
5246 * parse a XML schema Element declaration
5247 * *WARNING* this interface is highly subject to change
5248 *
William M. Bracke7091952004-05-11 15:09:58 +00005249 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005250 */
5251static xmlSchemaElementPtr
5252xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005253 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005254{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005255 const xmlChar *name = NULL;
5256 const xmlChar *attrValue;
5257 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005258 xmlSchemaElementPtr ret;
5259 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005260 const xmlChar *oldcontainer;
5261 xmlAttrPtr attr, nameAttr;
5262 int minOccurs, maxOccurs;
5263 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005264
5265 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5266 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005267
Daniel Veillard4255d502002-04-16 15:50:10 +00005268 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5269 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005270
Daniel Veillardc0826a72004-08-10 14:17:33 +00005271 oldcontainer = ctxt->container;
5272
5273 nameAttr = xmlSchemaGetPropNode(node, "name");
5274 attr = xmlSchemaGetPropNode(node, "ref");
5275 if ((topLevel) || (attr == NULL)) {
5276 if (nameAttr == NULL) {
5277 xmlSchemaPMissingAttrErr(ctxt,
5278 XML_SCHEMAP_S4S_ATTR_MISSING,
5279 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5280 "name", NULL);
5281 return (NULL);
5282 }
5283 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5284 } else {
5285 isRef = 1;
5286
5287 }
5288 /*
5289 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5290 * to no component at all
5291 * TODO: It might be better to validate the element, even if it won't be
5292 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005293 */
5294 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5295 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005296 if ((minOccurs == 0) && (maxOccurs == 0))
5297 return (NULL);
5298 /*
5299 * If we get a "ref" attribute on a local <element> we will assume it's
5300 * a reference - even if there's a "name" attribute; this seems to be more
5301 * robust.
5302 */
5303 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005304 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005305 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5306
5307 /*
5308 * Parse as a particle.
5309 */
5310 xmlSchemaPValAttrNodeQName(ctxt, schema,
5311 (xmlChar **) &xmlSchemaElemDesAttrRef,
5312 NULL, attr, &refNs, &refPrefix, &ref);
5313
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005314 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005315 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005316 if (ret == NULL) {
5317 if (repName != NULL)
5318 xmlFree(repName);
5319 return (NULL);
5320 }
5321 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5322 ret->node = node;
5323 ret->ref = ref;
5324 ret->refNs = refNs;
5325 ret->refPrefix = refPrefix;
5326 ret->flags |= XML_SCHEMAS_ELEM_REF;
5327 /*
5328 * Check for illegal attributes.
5329 */
5330 /*
5331 * 3.3.3 : 2.1
5332 * One of ref or name must be present, but not both
5333 */
5334 if (nameAttr != NULL) {
5335 xmlSchemaPMutualExclAttrErr(ctxt,
5336 XML_SCHEMAP_SRC_ELEMENT_2_1,
5337 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5338 "ref", "name");
5339 }
5340 /* 3.3.3 : 2.2 */
5341 attr = node->properties;
5342 while (attr != NULL) {
5343 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005344 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5345 xmlStrEqual(attr->name, BAD_CAST "name") ||
5346 xmlStrEqual(attr->name, BAD_CAST "id") ||
5347 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5348 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5349 {
5350 attr = attr->next;
5351 continue;
5352 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005353 xmlSchemaPCustomAttrErr(ctxt,
5354 XML_SCHEMAP_SRC_ELEMENT_2_2,
5355 &repName, (xmlSchemaTypePtr) ret, attr,
5356 "Only the attributes 'minOccurs', 'maxOccurs' and "
5357 "'id' are allowed in addition to 'ref'");
5358 break;
5359 }
5360 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5361 xmlSchemaPIllegalAttrErr(ctxt,
5362 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5363 &repName, (xmlSchemaTypePtr) ret, attr);
5364 }
5365 attr = attr->next;
5366 }
5367 } else {
5368 const xmlChar *ns = NULL, *fixed;
5369
5370 /*
5371 * Parse as an element declaration.
5372 */
5373 if (xmlSchemaPValAttrNode(ctxt,
5374 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5375 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5376 return (NULL);
5377 /*
5378 * Evaluate the target namespace.
5379 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005380 if (topLevel) {
5381 ns = schema->targetNamespace;
5382 } else {
5383 attr = xmlSchemaGetPropNode(node, "form");
5384 if (attr != NULL) {
5385 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5386 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005387 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005388 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5389 xmlSchemaPSimpleTypeErr(ctxt,
5390 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5391 &repName, NULL, (xmlNodePtr) attr,
5392 NULL, "(qualified | unqualified)",
5393 attrValue, NULL, NULL, NULL);
5394 }
5395 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5396 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005397 }
5398 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005399 if (ret == NULL) {
5400 if (repName != NULL)
5401 xmlFree(repName);
5402 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005403 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005404 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5405 ret->node = node;
5406 /*
5407 * Check for illegal attributes.
5408 */
William M. Bracke7091952004-05-11 15:09:58 +00005409 attr = node->properties;
5410 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005411 if (attr->ns == NULL) {
5412 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5413 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5414 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5415 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5416 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5417 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005418 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5419 {
5420 if (topLevel == 0) {
5421 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005422 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005423 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5424 {
5425 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5426 /*
5427 * 3.3.6 : 3 If there is a non-·absent· {substitution
5428 * group affiliation}, then {scope} must be global.
5429 * TODO: This one is redundant, since the S4S does
5430 * prohibit this attribute on local declarations already;
5431 * so why an explicit error code? Weird spec.
5432 * TODO: Move this to the proper constraint layer.
5433 * TODO: Or better wait for spec 1.1 to come.
5434 */
5435 xmlSchemaPIllegalAttrErr(ctxt,
5436 XML_SCHEMAP_E_PROPS_CORRECT_3,
5437 &repName, (xmlSchemaTypePtr) ret, attr);
5438 } else {
5439 xmlSchemaPIllegalAttrErr(ctxt,
5440 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5441 &repName, (xmlSchemaTypePtr) ret, attr);
5442 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005443 }
5444 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5445 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5446 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5447
5448 xmlSchemaPIllegalAttrErr(ctxt,
5449 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5450 &repName, (xmlSchemaTypePtr) ret, attr);
5451 }
5452 }
5453 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5454
5455 xmlSchemaPIllegalAttrErr(ctxt,
5456 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5457 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005458 }
5459 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005460 }
William M. Bracke7091952004-05-11 15:09:58 +00005461 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005462 * Extract/validate attributes.
5463 */
5464 if (topLevel) {
5465 /*
5466 * Process top attributes of global element declarations here.
5467 */
5468 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5469 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5470 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5471 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5472 &(ret->substGroupNs), NULL, &(ret->substGroup));
5473 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5474 node, "abstract", 0))
5475 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5476 /*
5477 * Attribute "final".
5478 */
5479 attr = xmlSchemaGetPropNode(node, "final");
5480 if (attr == NULL) {
5481 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5482 } else {
5483 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5484 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5485 -1,
5486 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5487 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5488 xmlSchemaPSimpleTypeErr(ctxt,
5489 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5490 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005491 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005492 attrValue, NULL, NULL, NULL);
5493 }
5494 }
5495 }
5496 /*
5497 * Attribute "block".
5498 */
5499 attr = xmlSchemaGetPropNode(node, "block");
5500 if (attr == NULL) {
5501 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5502 } else {
5503 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5504 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5505 -1,
5506 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5507 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5508 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5509 xmlSchemaPSimpleTypeErr(ctxt,
5510 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5511 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005512 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005513 "restriction | substitution))", attrValue,
5514 NULL, NULL, NULL);
5515 }
5516 }
5517 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5518 node, "nillable", 0))
5519 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005520
Daniel Veillardc0826a72004-08-10 14:17:33 +00005521 xmlSchemaPValAttrQName(ctxt, schema,
5522 &repName, (xmlSchemaTypePtr) ret, node,
5523 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005524
Daniel Veillardc0826a72004-08-10 14:17:33 +00005525 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5526 attr = xmlSchemaGetPropNode(node, "fixed");
5527 if (attr != NULL) {
5528 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5529 if (ret->value != NULL) {
5530 /*
5531 * 3.3.3 : 1
5532 * default and fixed must not both be present.
5533 */
5534 xmlSchemaPMutualExclAttrErr(ctxt,
5535 XML_SCHEMAP_SRC_ELEMENT_1,
5536 &repName, (xmlSchemaTypePtr) ret, attr,
5537 "default", "fixed");
5538 } else {
5539 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5540 ret->value = fixed;
5541 }
5542 }
5543 }
5544 /*
5545 * Extract/validate common attributes.
5546 */
5547 /* TODO: Check ID: */
5548 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5549 ret->minOccurs = minOccurs;
5550 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005551 if (topLevel != 1)
5552 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5553 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 /*
5555 * And now for the children...
5556 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005557 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005558 child = node->children;
5559 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005560 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5561 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005562 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005563 if (isRef) {
5564 if (child != NULL) {
5565 xmlSchemaPContentErr(ctxt,
5566 XML_SCHEMAP_SRC_ELEMENT_2_2,
5567 &repName, (xmlSchemaTypePtr) ret, node, child,
5568 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005569 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005570 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005571 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005572 /*
5573 * 3.3.3 : 3
5574 * "type" and either <simpleType> or <complexType> are mutually
5575 * exclusive
5576 */
William M. Bracke7091952004-05-11 15:09:58 +00005577 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005578 xmlSchemaPContentErr(ctxt,
5579 XML_SCHEMAP_SRC_ELEMENT_3,
5580 &repName, (xmlSchemaTypePtr) ret, node, child,
5581 "The attribute 'type' and the <complexType> child are "
5582 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005583 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005584 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005585 child = child->next;
5586 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005587 /*
5588 * 3.3.3 : 3
5589 * "type" and either <simpleType> or <complexType> are
5590 * mutually exclusive
5591 */
William M. Bracke7091952004-05-11 15:09:58 +00005592 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005593 xmlSchemaPContentErr(ctxt,
5594 XML_SCHEMAP_SRC_ELEMENT_3,
5595 &repName, (xmlSchemaTypePtr) ret, node, child,
5596 "The attribute 'type' and the <simpleType> child are "
5597 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005598 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005599 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005600 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005601 }
William M. Bracke7091952004-05-11 15:09:58 +00005602 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005603 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005604 /*TODO*/ child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00005605 }
5606 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005607 xmlSchemaPContentErr(ctxt,
5608 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5609 &repName, (xmlSchemaTypePtr) ret, node, child,
5610 NULL, "(annotation?, ((simpleType | complexType)?, "
5611 "(unique | key | keyref)*))");
5612 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005613
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005615 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005616 /*
5617 * Cleanup.
5618 */
5619 if (repName != NULL)
5620 xmlFree(repName);
5621 /*
5622 * NOTE: Element Declaration Representation OK 4. will be checked at a
5623 * different layer.
5624 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005625 return (ret);
5626}
5627
5628/**
5629 * xmlSchemaParseUnion:
5630 * @ctxt: a schema validation context
5631 * @schema: the schema being built
5632 * @node: a subtree containing XML Schema informations
5633 *
5634 * parse a XML schema Union definition
5635 * *WARNING* this interface is highly subject to change
5636 *
William M. Bracke7091952004-05-11 15:09:58 +00005637 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005638 * 1 in case of success.
5639 */
5640static xmlSchemaTypePtr
5641xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005643{
5644 xmlSchemaTypePtr type, subtype, last = NULL;
5645 xmlNodePtr child = NULL;
5646 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005647 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005648
5649 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5650 return (NULL);
5651
William M. Brack2f2a6632004-08-20 23:09:47 +00005652 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5653 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005654 if (type == NULL)
5655 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005656 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005657 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005658 /*
5659 * Check for illegal attributes.
5660 */
5661 attr = node->properties;
5662 while (attr != NULL) {
5663 if (attr->ns == NULL) {
5664 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5665 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5666 xmlSchemaPIllegalAttrErr(ctxt,
5667 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5668 NULL, type, attr);
5669 }
5670 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5671 xmlSchemaPIllegalAttrErr(ctxt,
5672 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5673 NULL, type, attr);
5674 }
5675 attr = attr->next;
5676 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005677 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005678 /*
5679 * Attribute "memberTypes". This is a list of QNames.
5680 * TODO: Validate the QNames.
5681 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005682 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005683 /*
5684 * And now for the children...
5685 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005686 child = node->children;
5687 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005688 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5689 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005691 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005692 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005693 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005694 if (subtype != NULL) {
5695 if (last == NULL) {
5696 type->subtypes = subtype;
5697 last = subtype;
5698 } else {
5699 last->next = subtype;
5700 last = subtype;
5701 }
5702 last->next = NULL;
5703 }
5704 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005705 }
5706 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005707 /* TODO: Think about the error code. */
5708 xmlSchemaPContentErr(ctxt,
5709 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5710 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005711 }
5712 return (type);
5713}
5714
5715/**
5716 * xmlSchemaParseList:
5717 * @ctxt: a schema validation context
5718 * @schema: the schema being built
5719 * @node: a subtree containing XML Schema informations
5720 *
5721 * parse a XML schema List definition
5722 * *WARNING* this interface is highly subject to change
5723 *
William M. Bracke7091952004-05-11 15:09:58 +00005724 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005725 * 1 in case of success.
5726 */
5727static xmlSchemaTypePtr
5728xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005729 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005730{
5731 xmlSchemaTypePtr type, subtype;
5732 xmlNodePtr child = NULL;
5733 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005734 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005735
5736 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5737 return (NULL);
5738
William M. Brack2f2a6632004-08-20 23:09:47 +00005739 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5740 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005741 if (type == NULL)
5742 return (NULL);
5743 type->node = node;
5744 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005745 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005746 /*
5747 * Check for illegal attributes.
5748 */
5749 attr = node->properties;
5750 while (attr != NULL) {
5751 if (attr->ns == NULL) {
5752 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5753 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5754 xmlSchemaPIllegalAttrErr(ctxt,
5755 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5756 NULL, type, attr);
5757 }
5758 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5759 xmlSchemaPIllegalAttrErr(ctxt,
5760 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5761 NULL, type, attr);
5762 }
5763 attr = attr->next;
5764 }
5765 /*
5766 * Attribute "itemType".
5767 */
5768 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5769 node, "itemType", &(type->baseNs), NULL, &(type->base));
5770 /*
5771 * And now for the children...
5772 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005773 child = node->children;
5774 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005775 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5776 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005777 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005778 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005779 if (IS_SCHEMA(child, "simpleType")) {
5780 if (type->base != NULL) {
5781 xmlSchemaPCustomErr(ctxt,
5782 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5783 NULL, type, node,
5784 "The attribute 'itemType' and the <simpleType> child "
5785 "are mutually exclusive", NULL);
5786 } else {
5787 subtype = (xmlSchemaTypePtr)
5788 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5789 type->subtypes = subtype;
5790 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005791 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005792 }
5793 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005794 /* TODO: Think about the error code. */
5795 xmlSchemaPContentErr(ctxt,
5796 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5797 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005798 }
5799 return (type);
5800}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005801
Daniel Veillard4255d502002-04-16 15:50:10 +00005802/**
5803 * xmlSchemaParseSimpleType:
5804 * @ctxt: a schema validation context
5805 * @schema: the schema being built
5806 * @node: a subtree containing XML Schema informations
5807 *
5808 * parse a XML schema Simple Type definition
5809 * *WARNING* this interface is highly subject to change
5810 *
William M. Bracke7091952004-05-11 15:09:58 +00005811 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005812 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 */
5814static xmlSchemaTypePtr
5815xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005816 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005817{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005818 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005820 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005821 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005822 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005823
5824 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5825 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005826
Daniel Veillardc0826a72004-08-10 14:17:33 +00005827 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005828 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005829 if (attr == NULL) {
5830 xmlSchemaPMissingAttrErr(ctxt,
5831 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005832 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005833 "name", NULL);
5834 return (NULL);
5835 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005836 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005837 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005838 return (NULL);
5839 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005840 }
5841
5842 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005843 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005844
Daniel Veillard01fa6152004-06-29 17:04:39 +00005845 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005846 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005847 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005848 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005849 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005850 if (type == NULL)
5851 return (NULL);
5852 type->node = node;
5853 type->type = XML_SCHEMA_TYPE_SIMPLE;
5854 /*
5855 * Check for illegal attributes.
5856 */
5857 attr = node->properties;
5858 while (attr != NULL) {
5859 if (attr->ns == NULL) {
5860 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5861 xmlSchemaPIllegalAttrErr(ctxt,
5862 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005863 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005864 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005865 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5866 xmlSchemaPIllegalAttrErr(ctxt,
5867 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005868 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005869 }
5870 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005871 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005872 } else {
5873 /*
5874 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005875 *
5876 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005877 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005878 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005879 if (type == NULL)
5880 return (NULL);
5881 type->node = node;
5882 type->type = XML_SCHEMA_TYPE_SIMPLE;
5883 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5884 /*
5885 * Check for illegal attributes.
5886 */
5887 attr = node->properties;
5888 while (attr != NULL) {
5889 if (attr->ns == NULL) {
5890 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5891 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005892 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005893 xmlSchemaPIllegalAttrErr(ctxt,
5894 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005895 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005896 }
5897 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5898 xmlSchemaPIllegalAttrErr(ctxt,
5899 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005900 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005901 }
5902 attr = attr->next;
5903 }
5904 /*
5905 * Attribute "final".
5906 */
5907 attr = xmlSchemaGetPropNode(node, "final");
5908 if (attr == NULL) {
5909 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5910 } else {
5911 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5912 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5913 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5914 XML_SCHEMAS_TYPE_FINAL_LIST,
5915 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5916
5917 xmlSchemaPSimpleTypeErr(ctxt,
5918 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005919 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005920 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005921 attrValue, NULL, NULL, NULL);
5922 }
5923 }
5924 }
5925 /* TODO: Check id. */
5926 type->id = xmlSchemaGetProp(ctxt, node, "id");
5927 /*
5928 * And now for the children...
5929 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005930 oldCtxtType = ctxt->ctxtType;
5931 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005932 ctxt->ctxtType = type;
5933 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005934 child = node->children;
5935 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005936 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5937 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005938 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005939 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005940 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005941 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005942 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005943 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005944 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005945 subtype = (xmlSchemaTypePtr)
5946 xmlSchemaParseList(ctxt, schema, child);
5947 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005948 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005949 subtype = (xmlSchemaTypePtr)
5950 xmlSchemaParseUnion(ctxt, schema, child);
5951 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005952 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005953 type->subtypes = subtype;
5954 if ((child != NULL) || (subtype == NULL)) {
5955 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005956 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005957 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005958 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005959 ctxt->parentItem = oldParentItem;
5960 ctxt->ctxtType = oldCtxtType;
5961 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005962
Daniel Veillard4255d502002-04-16 15:50:10 +00005963 return (type);
5964}
5965
5966
5967/**
5968 * xmlSchemaParseGroup:
5969 * @ctxt: a schema validation context
5970 * @schema: the schema being built
5971 * @node: a subtree containing XML Schema informations
5972 *
5973 * parse a XML schema Group definition
5974 * *WARNING* this interface is highly subject to change
5975 *
William M. Bracke7091952004-05-11 15:09:58 +00005976 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005977 * 1 in case of success.
5978 */
5979static xmlSchemaTypePtr
5980xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005981 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005982{
5983 xmlSchemaTypePtr type, subtype;
5984 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005985 const xmlChar *name;
5986 const xmlChar *ref = NULL, *refNs = NULL;
5987 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005988 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005989
5990 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5991 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005992 /*
5993 * TODO: Validate the element even if no item is created
5994 * (i.e. min/maxOccurs == 0).
5995 */
5996 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5997 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
5998 if ((minOccurs == 0) && (maxOccurs == 0)) {
5999 return (NULL);
6000 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006001 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006002 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006003 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6004 if (ref == NULL) {
6005 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006006 XML_SCHEMAP_GROUP_NONAME_NOREF,
6007 "Group definition or particle: One of the attributes \"name\" "
6008 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006009 return (NULL);
6010 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006011 if (refNs == NULL)
6012 refNs = schema->targetNamespace;
6013 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
6014 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006015 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006016 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006017 if (type == NULL)
6018 return (NULL);
6019 type->node = node;
6020 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00006021 if (topLevel)
6022 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006023 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006024 type->ref = ref;
6025 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006026 type->minOccurs = minOccurs;
6027 type->maxOccurs = maxOccurs;
6028 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006029 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006030
6031 child = node->children;
6032 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006033 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6034 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006035 }
6036 subtype = NULL;
6037 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038 subtype = (xmlSchemaTypePtr)
6039 xmlSchemaParseAll(ctxt, schema, child);
6040 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006041 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006042 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6043 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006045 subtype = (xmlSchemaTypePtr)
6046 xmlSchemaParseSequence(ctxt, schema, child);
6047 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006048 }
6049 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006050 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006052 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006053 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006054 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006055 }
6056
6057 return (type);
6058}
6059
6060/**
6061 * xmlSchemaParseAll:
6062 * @ctxt: a schema validation context
6063 * @schema: the schema being built
6064 * @node: a subtree containing XML Schema informations
6065 *
6066 * parse a XML schema All definition
6067 * *WARNING* this interface is highly subject to change
6068 *
William M. Bracke7091952004-05-11 15:09:58 +00006069 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006070 * 1 in case of success.
6071 */
6072static xmlSchemaTypePtr
6073xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006074 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006075{
6076 xmlSchemaTypePtr type, subtype, last = NULL;
6077 xmlNodePtr child = NULL;
6078 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006079 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006080
6081 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6082 return (NULL);
6083
6084
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006085 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006086 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 if (type == NULL)
6088 return (NULL);
6089 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006090 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006091 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006092
6093 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6094 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006095
6096 oldcontainer = ctxt->container;
6097 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006098 child = node->children;
6099 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006100 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6101 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006102 }
6103 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006104 subtype = (xmlSchemaTypePtr)
6105 xmlSchemaParseElement(ctxt, schema, child, 0);
6106 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006107 if (subtype->minOccurs > 1)
6108 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006109 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006110 NULL, NULL);
6111 if (subtype->maxOccurs > 1)
6112 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006113 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006114 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006115 if (last == NULL) {
6116 type->subtypes = subtype;
6117 last = subtype;
6118 } else {
6119 last->next = subtype;
6120 last = subtype;
6121 }
6122 last->next = NULL;
6123 }
6124 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006125 }
6126 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006127 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006128 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006129 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006130 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006131 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006132 return (type);
6133}
6134
6135/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006136 * xmlSchemaCleanupDoc:
6137 * @ctxt: a schema validation context
6138 * @node: the root of the document.
6139 *
6140 * removes unwanted nodes in a schemas document tree
6141 */
6142static void
6143xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6144{
6145 xmlNodePtr delete, cur;
6146
6147 if ((ctxt == NULL) || (root == NULL)) return;
6148
6149 /*
6150 * Remove all the blank text nodes
6151 */
6152 delete = NULL;
6153 cur = root;
6154 while (cur != NULL) {
6155 if (delete != NULL) {
6156 xmlUnlinkNode(delete);
6157 xmlFreeNode(delete);
6158 delete = NULL;
6159 }
6160 if (cur->type == XML_TEXT_NODE) {
6161 if (IS_BLANK_NODE(cur)) {
6162 if (xmlNodeGetSpacePreserve(cur) != 1) {
6163 delete = cur;
6164 }
6165 }
6166 } else if ((cur->type != XML_ELEMENT_NODE) &&
6167 (cur->type != XML_CDATA_SECTION_NODE)) {
6168 delete = cur;
6169 goto skip_children;
6170 }
6171
6172 /*
6173 * Skip to next node
6174 */
6175 if (cur->children != NULL) {
6176 if ((cur->children->type != XML_ENTITY_DECL) &&
6177 (cur->children->type != XML_ENTITY_REF_NODE) &&
6178 (cur->children->type != XML_ENTITY_NODE)) {
6179 cur = cur->children;
6180 continue;
6181 }
6182 }
6183 skip_children:
6184 if (cur->next != NULL) {
6185 cur = cur->next;
6186 continue;
6187 }
6188
6189 do {
6190 cur = cur->parent;
6191 if (cur == NULL)
6192 break;
6193 if (cur == root) {
6194 cur = NULL;
6195 break;
6196 }
6197 if (cur->next != NULL) {
6198 cur = cur->next;
6199 break;
6200 }
6201 } while (cur != NULL);
6202 }
6203 if (delete != NULL) {
6204 xmlUnlinkNode(delete);
6205 xmlFreeNode(delete);
6206 delete = NULL;
6207 }
6208}
6209
William M. Brack2f2a6632004-08-20 23:09:47 +00006210
6211/**
6212 * xmlSchemaImportSchema
6213 *
6214 * @ctxt: a schema validation context
6215 * @schemaLocation: an URI defining where to find the imported schema
6216 *
6217 * import a XML schema
6218 * *WARNING* this interface is highly subject to change
6219 *
6220 * Returns -1 in case of error and 1 in case of success.
6221 */
6222#if 0
6223static xmlSchemaImportPtr
6224xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6225 const xmlChar *schemaLocation)
6226{
6227 xmlSchemaImportPtr import;
6228 xmlSchemaParserCtxtPtr newctxt;
6229
6230 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6231 if (newctxt == NULL) {
6232 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6233 NULL);
6234 return (NULL);
6235 }
6236 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6237 /* Keep the same dictionnary for parsing, really */
6238 xmlDictReference(ctxt->dict);
6239 newctxt->dict = ctxt->dict;
6240 newctxt->includes = 0;
6241 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6242
6243 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6244 ctxt->userData);
6245
6246 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6247 if (import == NULL) {
6248 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6249 NULL);
6250 xmlSchemaFreeParserCtxt(newctxt);
6251 return (NULL);
6252 }
6253
6254 memset(import, 0, sizeof(xmlSchemaImport));
6255 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6256 import->schema = xmlSchemaParse(newctxt);
6257
6258 if (import->schema == NULL) {
6259 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006260 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006261 "Failed to import schema from location \"%s\".\n",
6262 schemaLocation, NULL);
6263
6264 xmlSchemaFreeParserCtxt(newctxt);
6265 /* The schemaLocation is held by the dictionary.
6266 if (import->schemaLocation != NULL)
6267 xmlFree((xmlChar *)import->schemaLocation);
6268 */
6269 xmlFree(import);
6270 return NULL;
6271 }
6272
6273 xmlSchemaFreeParserCtxt(newctxt);
6274 return import;
6275}
6276#endif
6277
6278static void
6279xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6280{
6281 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6282 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6283
6284 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6285 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6286
6287 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6288 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6289 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6290 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6291 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6292 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6293 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6294 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6295
6296 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6297 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6298 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6299 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6300 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6301 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6302}
6303
6304static void
6305xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6306 xmlSchemaPtr schema,
6307 xmlNodePtr node)
6308{
6309 xmlAttrPtr attr;
6310 const xmlChar *val;
6311
6312 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6313 if (attr != NULL) {
6314 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6315 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6316 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6317 xmlSchemaPSimpleTypeErr(ctxt,
6318 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6319 NULL, NULL, (xmlNodePtr) attr, NULL,
6320 "(qualified | unqualified)", val, NULL, NULL, NULL);
6321 }
6322 }
6323
6324 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6325 if (attr != NULL) {
6326 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6327 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6328 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6329 xmlSchemaPSimpleTypeErr(ctxt,
6330 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6331 NULL, NULL, (xmlNodePtr) attr, NULL,
6332 "(qualified | unqualified)", val, NULL, NULL, NULL);
6333 }
6334 }
6335
6336 attr = xmlSchemaGetPropNode(node, "finalDefault");
6337 if (attr != NULL) {
6338 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6339 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6340 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6341 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6342 -1,
6343 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6344 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6345 xmlSchemaPSimpleTypeErr(ctxt,
6346 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6347 NULL, NULL, (xmlNodePtr) attr, NULL,
6348 "(#all | List of (extension | restriction | list | union))",
6349 val, NULL, NULL, NULL);
6350 }
6351 }
6352
6353 attr = xmlSchemaGetPropNode(node, "blockDefault");
6354 if (attr != NULL) {
6355 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6356 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6357 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6358 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6359 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6360 xmlSchemaPSimpleTypeErr(ctxt,
6361 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6362 NULL, NULL, (xmlNodePtr) attr, NULL,
6363 "(#all | List of (extension | restriction | substitution))",
6364 val, NULL, NULL, NULL);
6365 }
6366 }
6367}
6368
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006369/**
6370 * xmlSchemaParseSchemaTopLevel:
6371 * @ctxt: a schema validation context
6372 * @schema: the schemas
6373 * @nodes: the list of top level nodes
6374 *
6375 * Returns the internal XML Schema structure built from the resource or
6376 * NULL in case of error
6377 */
6378static void
6379xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6380 xmlSchemaPtr schema, xmlNodePtr nodes)
6381{
6382 xmlNodePtr child;
6383 xmlSchemaAnnotPtr annot;
6384
6385 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6386 return;
6387
6388 child = nodes;
6389 while ((IS_SCHEMA(child, "include")) ||
6390 (IS_SCHEMA(child, "import")) ||
6391 (IS_SCHEMA(child, "redefine")) ||
6392 (IS_SCHEMA(child, "annotation"))) {
6393 if (IS_SCHEMA(child, "annotation")) {
6394 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6395 if (schema->annot == NULL)
6396 schema->annot = annot;
6397 else
6398 xmlSchemaFreeAnnot(annot);
6399 } else if (IS_SCHEMA(child, "import")) {
6400 xmlSchemaParseImport(ctxt, schema, child);
6401 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006402 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006403 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006404 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006405 } else if (IS_SCHEMA(child, "redefine")) {
6406 TODO
6407 }
6408 child = child->next;
6409 }
6410 while (child != NULL) {
6411 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006412 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006413 child = child->next;
6414 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006415 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006416 child = child->next;
6417 } else if (IS_SCHEMA(child, "element")) {
6418 xmlSchemaParseElement(ctxt, schema, child, 1);
6419 child = child->next;
6420 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006421 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006422 child = child->next;
6423 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006424 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006425 child = child->next;
6426 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006427 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006428 child = child->next;
6429 } else if (IS_SCHEMA(child, "notation")) {
6430 xmlSchemaParseNotation(ctxt, schema, child);
6431 child = child->next;
6432 } else {
6433 xmlSchemaPErr2(ctxt, NULL, child,
6434 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006435 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006436 child->name, NULL);
6437 child = child->next;
6438 }
6439 while (IS_SCHEMA(child, "annotation")) {
6440 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6441 if (schema->annot == NULL)
6442 schema->annot = annot;
6443 else
6444 xmlSchemaFreeAnnot(annot);
6445 child = child->next;
6446 }
6447 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006448 ctxt->parentItem = NULL;
6449 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006450}
6451
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006452static xmlSchemaImportPtr
6453xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6454 xmlHashTablePtr *imports,
6455 const xmlChar *nsName)
6456{
6457 xmlSchemaImportPtr ret;
6458
6459 if (*imports == NULL) {
6460 *imports = xmlHashCreate(10);
6461 if (*imports == NULL) {
6462 xmlSchemaPCustomErr(ctxt,
6463 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6464 NULL, NULL, (xmlNodePtr) ctxt->doc,
6465 "Internal error: failed to build the import table",
6466 NULL);
6467 return (NULL);
6468 }
6469 }
6470 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6471 if (ret == NULL) {
6472 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6473 return (NULL);
6474 }
6475 memset(ret, 0, sizeof(xmlSchemaImport));
6476 if (nsName == NULL)
6477 nsName = XML_SCHEMAS_NO_NAMESPACE;
6478 xmlHashAddEntry(*imports, nsName, ret);
6479
6480 return (ret);
6481}
6482
6483static int
6484xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006485 xmlSchemaPtr schema,
6486 xmlNodePtr node,
6487 const xmlChar *nsName,
6488 const xmlChar *location,
6489 xmlDocPtr *doc,
6490 const xmlChar **targetNamespace,
6491 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006492{
6493 xmlParserCtxtPtr parserCtxt;
6494 xmlSchemaImportPtr import;
6495 const xmlChar *ns;
6496 xmlNodePtr root;
6497
6498 /*
6499 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6500 * <xsi:noNamespaceSchemaLocation>.
6501 */
6502 *doc = NULL;
6503 /*
6504 * Given that the schemaLocation [attribute] is only a hint, it is open
6505 * to applications to ignore all but the first <import> for a given
6506 * namespace, regardless of the ·actual value· of schemaLocation, but
6507 * such a strategy risks missing useful information when new
6508 * schemaLocations are offered.
6509 *
6510 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6511 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6512 * valid or not.
6513 * We will follow XSV here.
6514 */
6515 if (location == NULL) {
6516 /*
6517 * Schema Document Location Strategy:
6518 *
6519 * 3 Based on the namespace name, identify an existing schema document,
6520 * either as a resource which is an XML document or a <schema> element
6521 * information item, in some local schema repository;
6522 *
6523 * 5 Attempt to resolve the namespace name to locate such a resource.
6524 *
6525 * NOTE: Those stategies are not supported, so we will skip.
6526 */
6527 return (0);
6528 }
6529 if (nsName == NULL)
6530 ns = XML_SCHEMAS_NO_NAMESPACE;
6531 else
6532 ns = nsName;
6533
6534 import = xmlHashLookup(schema->schemasImports, ns);
6535 if (import != NULL) {
6536 /*
6537 * There was a valid resource for the specified namespace already
6538 * defined, so skip.
6539 * TODO: This might be changed someday to allow import of
6540 * components from multiple documents for a single target namespace.
6541 */
6542 return (0);
6543 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006544
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006545 /*
6546 * Schema Document Location Strategy:
6547 *
6548 * 2 Based on the location URI, identify an existing schema document,
6549 * either as a resource which is an XML document or a <schema> element
6550 * information item, in some local schema repository;
6551 *
6552 * 4 Attempt to resolve the location URI, to locate a resource on the
6553 * web which is or contains or references a <schema> element;
6554 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6555 *
6556 */
6557 if ((absolute == 0) && (node != NULL)) {
6558 xmlChar *base, *URI;
6559
6560 base = xmlNodeGetBase(node->doc, node);
6561 if (base == NULL) {
6562 URI = xmlBuildURI(location, node->doc->URL);
6563 } else {
6564 URI = xmlBuildURI(location, base);
6565 xmlFree(base);
6566 }
6567 if (URI != NULL) {
6568 location = xmlDictLookup(ctxt->dict, URI, -1);
6569 xmlFree(URI);
6570 }
6571 }
6572 parserCtxt = xmlNewParserCtxt();
6573 if (parserCtxt == NULL) {
6574 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6575 "allocating a parser context", NULL);
6576 return(-1);
6577 }
6578
6579 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6580 NULL, SCHEMAS_PARSE_OPTIONS);
6581
6582 /*
6583 * 2.1 The referent is (a fragment of) a resource which is an
6584 * XML document (see clause 1.1), which in turn corresponds to
6585 * a <schema> element information item in a well-formed information
6586 * set, which in turn corresponds to a valid schema.
6587 * TODO: What to do with the "fragment" stuff?
6588 *
6589 * 2.2 The referent is a <schema> element information item in
6590 * a well-formed information set, which in turn corresponds
6591 * to a valid schema.
6592 * NOTE: 2.2 won't apply, since only XML documents will be processed
6593 * here.
6594 */
6595 if (*doc == NULL) {
6596 xmlErrorPtr lerr;
6597 /*
6598 * It is *not* an error for the application schema reference
6599 * strategy to fail.
6600 *
6601 * If the doc is NULL and the parser error is an IO error we
6602 * will assume that the resource could not be located or accessed.
6603 *
6604 * TODO: Try to find specific error codes to react only on
6605 * localisation failures.
6606 *
6607 * TODO, FIXME: Check the spec: is a namespace added to the imported
6608 * namespaces, even if the schemaLocation did not provide
6609 * a resource? I guess so, since omitting the "schemaLocation"
6610 * attribute, imports a namespace as well.
6611 */
6612 lerr = xmlGetLastError();
6613 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6614 xmlFreeParserCtxt(parserCtxt);
6615 return(0);
6616 }
6617
6618 xmlSchemaPCustomErr(ctxt,
6619 XML_SCHEMAP_SRC_IMPORT_2_1,
6620 NULL, NULL, node,
6621 "Failed to parse the resource '%s' for import",
6622 location);
6623 xmlFreeParserCtxt(parserCtxt);
6624 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6625 }
6626 xmlFreeParserCtxt(parserCtxt);
6627
6628 root = xmlDocGetRootElement(*doc);
6629 if (root == NULL) {
6630 xmlSchemaPCustomErr(ctxt,
6631 XML_SCHEMAP_SRC_IMPORT_2_1,
6632 NULL, NULL, node,
6633 "The XML document '%s' to be imported has no document "
6634 "element", location);
6635 xmlFreeDoc(*doc);
6636 *doc = NULL;
6637 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6638 }
6639
6640 xmlSchemaCleanupDoc(ctxt, root);
6641
6642 if (!IS_SCHEMA(root, "schema")) {
6643 xmlSchemaPCustomErr(ctxt,
6644 XML_SCHEMAP_SRC_IMPORT_2_1,
6645 NULL, NULL, node,
6646 "The XML document '%s' to be imported is not a XML schema document",
6647 location);
6648 xmlFreeDoc(*doc);
6649 *doc = NULL;
6650 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6651 }
6652 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6653 /*
6654 * Schema Representation Constraint: Import Constraints and Semantics
6655 */
6656 if (nsName == NULL) {
6657 if (*targetNamespace != NULL) {
6658 xmlSchemaPCustomErr(ctxt,
6659 XML_SCHEMAP_SRC_IMPORT_3_2,
6660 NULL, NULL, node,
6661 "The XML schema to be imported is not expected "
6662 "to have a target namespace; this differs from "
6663 "its target namespace of '%s'", *targetNamespace);
6664 xmlFreeDoc(*doc);
6665 *doc = NULL;
6666 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6667 }
6668 } else {
6669 if (*targetNamespace == NULL) {
6670 xmlSchemaPCustomErr(ctxt,
6671 XML_SCHEMAP_SRC_IMPORT_3_1,
6672 NULL, NULL, node,
6673 "The XML schema to be imported is expected to have a target "
6674 "namespace of '%s'", nsName);
6675 xmlFreeDoc(*doc);
6676 *doc = NULL;
6677 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6678 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6679 xmlSchemaPCustomErrExt(ctxt,
6680 XML_SCHEMAP_SRC_IMPORT_3_1,
6681 NULL, NULL, node,
6682 "The XML schema to be imported is expected to have a "
6683 "target namespace of '%s'; this differs from "
6684 "its target namespace of '%s'",
6685 nsName, *targetNamespace, NULL);
6686 xmlFreeDoc(*doc);
6687 *doc = NULL;
6688 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6689 }
6690 }
6691
6692 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6693 if (import == NULL) {
6694 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6695 NULL, NULL, NULL,
6696 "Internal error: xmlSchemaAcquireSchemaDoc, "
6697 "failed to build import table", NULL);
6698 xmlFreeDoc(*doc);
6699 *doc = NULL;
6700 return (-1);
6701 }
6702 import->schemaLocation = location;
6703 import->doc = *doc;
6704 return (0);
6705}
William M. Brack2f2a6632004-08-20 23:09:47 +00006706
6707/**
6708 * xmlSchemaParseImport:
6709 * @ctxt: a schema validation context
6710 * @schema: the schema being built
6711 * @node: a subtree containing XML Schema informations
6712 *
6713 * parse a XML schema Import definition
6714 * *WARNING* this interface is highly subject to change
6715 *
6716 * Returns 0 in case of success, a positive error code if
6717 * not valid and -1 in case of an internal error.
6718 */
6719static int
6720xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6721 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006722{
6723 xmlNodePtr child;
6724 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006725 const xmlChar *schemaLocation = NULL;
6726 const xmlChar *targetNamespace, *oldTNS, *url;
6727 xmlAttrPtr attr;
6728 xmlDocPtr doc;
6729 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006730 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006731
6732
6733 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6734 return (-1);
6735
6736 /*
6737 * Check for illegal attributes.
6738 */
6739 attr = node->properties;
6740 while (attr != NULL) {
6741 if (attr->ns == NULL) {
6742 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6743 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6744 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6745 xmlSchemaPIllegalAttrErr(ctxt,
6746 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6747 NULL, NULL, attr);
6748 }
6749 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6750 xmlSchemaPIllegalAttrErr(ctxt,
6751 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6752 NULL, NULL, attr);
6753 }
6754 attr = attr->next;
6755 }
6756 /*
6757 * Extract and validate attributes.
6758 */
6759 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6760 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6761 &namespace) != 0) {
6762 xmlSchemaPSimpleTypeErr(ctxt,
6763 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6764 NULL, NULL, node,
6765 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6766 NULL, namespace, NULL, NULL, NULL);
6767 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6768 }
6769
6770 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6771 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6772 &schemaLocation) != 0) {
6773 xmlSchemaPSimpleTypeErr(ctxt,
6774 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6775 NULL, NULL, node,
6776 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6777 NULL, namespace, NULL, NULL, NULL);
6778 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6779 }
6780 /*
6781 * And now for the children...
6782 */
6783 child = node->children;
6784 if (IS_SCHEMA(child, "annotation")) {
6785 /*
6786 * the annotation here is simply discarded ...
6787 */
6788 child = child->next;
6789 }
6790 if (child != NULL) {
6791 xmlSchemaPContentErr(ctxt,
6792 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6793 NULL, NULL, node, child, NULL,
6794 "(annotation?)");
6795 }
6796 /*
6797 * Apply additional constraints.
6798 */
6799 if (namespace != NULL) {
6800 /*
6801 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6802 * must not match the ·actual value· of the enclosing <schema>'s
6803 * targetNamespace [attribute].
6804 */
6805 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6806 xmlSchemaPCustomErr(ctxt,
6807 XML_SCHEMAP_SRC_IMPORT_1_1,
6808 NULL, NULL, node,
6809 "The value of the attribute 'namespace' must not match "
6810 "the target namespace '%s' of the importing schema",
6811 schema->targetNamespace);
6812 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6813 }
6814 } else {
6815 /*
6816 * 1.2 If the namespace [attribute] is not present, then the enclosing
6817 * <schema> must have a targetNamespace [attribute].
6818 */
6819 if (schema->targetNamespace == NULL) {
6820 xmlSchemaPCustomErr(ctxt,
6821 XML_SCHEMAP_SRC_IMPORT_1_2,
6822 NULL, NULL, node,
6823 "The attribute 'namespace' must be existent if "
6824 "the importing schema has no target namespace",
6825 NULL);
6826 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6827 }
6828 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006829 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006830 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006831 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006832 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6833 schemaLocation, &doc, &targetNamespace, 0);
6834 if (ret != 0) {
6835 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006836 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006837 return (ret);
6838 } else if (doc != NULL) {
6839 /*
6840 * Save and reset the context & schema.
6841 */
6842 url = ctxt->URL;
6843 /* TODO: Is using the doc->URL here correct? */
6844 ctxt->URL = doc->URL;
6845 flags = schema->flags;
6846 oldTNS = schema->targetNamespace;
6847 /*
6848 * Parse the schema.
6849 */
6850 root = xmlDocGetRootElement(doc);
6851 xmlSchemaClearSchemaDefaults(schema);
6852 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6853 schema->targetNamespace = targetNamespace;
6854 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6855 /*
6856 * Restore the context & schema.
6857 */
6858 schema->flags = flags;
6859 schema->targetNamespace = oldTNS;
6860 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00006861 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006862
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006863 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00006864}
6865
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006866/**
6867 * xmlSchemaParseInclude:
6868 * @ctxt: a schema validation context
6869 * @schema: the schema being built
6870 * @node: a subtree containing XML Schema informations
6871 *
6872 * parse a XML schema Include definition
6873 *
William M. Bracke7091952004-05-11 15:09:58 +00006874 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006875 * 1 in case of success.
6876 */
6877static int
6878xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6879 xmlNodePtr node)
6880{
6881 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006882 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006883 xmlDocPtr doc;
6884 xmlNodePtr root;
6885 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006886 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006887 xmlAttrPtr attr;
6888 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006889
6890
6891 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6892 return (-1);
6893
6894 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006895 * Check for illegal attributes.
6896 */
6897 attr = node->properties;
6898 while (attr != NULL) {
6899 if (attr->ns == NULL) {
6900 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6901 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6902 xmlSchemaPIllegalAttrErr(ctxt,
6903 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6904 NULL, NULL, attr);
6905 }
6906 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6907 xmlSchemaPIllegalAttrErr(ctxt,
6908 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6909 NULL, NULL, attr);
6910 }
6911 attr = attr->next;
6912 }
6913 /*
6914 * Extract and validate attributes.
6915 */
6916 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006917 * Preliminary step, extract the URI-Reference for the include and
6918 * make an URI from the base.
6919 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006920 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6921 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006922 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006923 xmlChar *uri = NULL;
6924
6925 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6926 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6927 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006928 base = xmlNodeGetBase(node->doc, node);
6929 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006930 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006931 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006932 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006933 xmlFree(base);
6934 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006935 if (uri != NULL) {
6936 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6937 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006938 }
6939 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006940 xmlSchemaPMissingAttrErr(ctxt,
6941 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6942 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006943 return (-1);
6944 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006945 /*
6946 * And now for the children...
6947 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006948 child = node->children;
6949 while (IS_SCHEMA(child, "annotation")) {
6950 /*
6951 * the annotations here are simply discarded ...
6952 */
6953 child = child->next;
6954 }
6955 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006956 xmlSchemaPContentErr(ctxt,
6957 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6958 NULL, NULL, node, child, NULL,
6959 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006960 }
6961
6962 /*
6963 * First step is to parse the input document into an DOM/Infoset
6964 */
6965 doc = xmlReadFile((const char *) schemaLocation, NULL,
6966 SCHEMAS_PARSE_OPTIONS);
6967 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006968 /*
6969 * TODO: It is not an error for the ·actual value· of the
6970 * schemaLocation [attribute] to fail to resolve it all, in which
6971 * case no corresponding inclusion is performed.
6972 * So do we need a warning report here?
6973 */
6974 xmlSchemaPCustomErr(ctxt,
6975 XML_SCHEMAP_FAILED_LOAD,
6976 NULL, NULL, node,
6977 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006978 return(-1);
6979 }
6980
6981 /*
6982 * Then extract the root of the schema
6983 */
6984 root = xmlDocGetRootElement(doc);
6985 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006986 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006987 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006988 NULL, NULL, node,
6989 "The included document '%s' has no document "
6990 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006991 xmlFreeDoc(doc);
6992 return (-1);
6993 }
6994
6995 /*
6996 * Remove all the blank text nodes
6997 */
6998 xmlSchemaCleanupDoc(ctxt, root);
6999
7000 /*
7001 * Check the schemas top level element
7002 */
7003 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007004 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007005 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007006 NULL, NULL, node,
7007 "The document '%s' to be included is not a schema document",
7008 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007009 xmlFreeDoc(doc);
7010 return (-1);
7011 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007012
William M. Brack2f2a6632004-08-20 23:09:47 +00007013 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007014 /*
7015 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7016 * value· is identical to the ·actual value· of the targetNamespace
7017 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7018 */
7019 if (targetNamespace != NULL) {
7020 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007021 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007022 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007023 NULL, NULL, node,
7024 "The target namespace of the included schema "
7025 "'%s' has to be absent, since the including schema "
7026 "has no target namespace",
7027 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007028 xmlFreeDoc(doc);
7029 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007030 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7031 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007032 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007033 NULL, NULL, node,
7034 "The target namespace '%s' of the included schema '%s' "
7035 "differs from '%s' of the including schema",
7036 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007037 xmlFreeDoc(doc);
7038 return (-1);
7039 }
7040 } else if (schema->targetNamespace != NULL) {
7041 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7042 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7043 } else
7044 wasConvertingNs = 1;
7045 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007046 /*
7047 * register the include
7048 */
7049 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7050 if (include == NULL) {
7051 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7052 xmlFreeDoc(doc);
7053 return (-1);
7054 }
7055
7056 memset(include, 0, sizeof(xmlSchemaInclude));
7057 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7058 include->doc = doc;
7059 include->next = schema->includes;
7060 schema->includes = include;
7061
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007062 /*
7063 * parse the declarations in the included file like if they
7064 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007065 */
7066 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007067 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007068 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007069 /*
7070 * The default values ("blockDefault", "elementFormDefault", etc.)
7071 * are set to the values of the included schema and restored afterwards.
7072 */
7073 saveFlags = schema->flags;
7074 xmlSchemaClearSchemaDefaults(schema);
7075 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007076 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007077 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007078 /*
7079 * Remove the converting flag.
7080 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007081 if ((wasConvertingNs == 0) &&
7082 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007083 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007084 return (1);
7085}
7086
7087/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007088 * xmlSchemaParseChoice:
7089 * @ctxt: a schema validation context
7090 * @schema: the schema being built
7091 * @node: a subtree containing XML Schema informations
7092 *
7093 * parse a XML schema Choice definition
7094 * *WARNING* this interface is highly subject to change
7095 *
William M. Bracke7091952004-05-11 15:09:58 +00007096 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007097 * 1 in case of success.
7098 */
7099static xmlSchemaTypePtr
7100xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007101 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007102{
7103 xmlSchemaTypePtr type, subtype, last = NULL;
7104 xmlNodePtr child = NULL;
7105 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007106 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007107 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007108
7109 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7110 return (NULL);
7111
7112
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007113 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007114 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007115 if (type == NULL)
7116 return (NULL);
7117 type->node = node;
7118 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007119 /*
7120 * Check for illegal attributes.
7121 */
7122 attr = node->properties;
7123 while (attr != NULL) {
7124 if (attr->ns == NULL) {
7125 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7126 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7127 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7128 xmlSchemaPIllegalAttrErr(ctxt,
7129 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7130 NULL, type, attr);
7131 }
7132 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7133 xmlSchemaPIllegalAttrErr(ctxt,
7134 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7135 NULL, type, attr);
7136 }
7137 attr = attr->next;
7138 }
7139 /*
7140 * Extract and validate attributes.
7141 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007142 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007143 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7144 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7145 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007146 /*
7147 * And now for the children...
7148 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007149 oldcontainer = ctxt->container;
7150 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007151 child = node->children;
7152 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007153 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7154 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007155 }
7156 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007157 (IS_SCHEMA(child, "group")) ||
7158 (IS_SCHEMA(child, "any")) ||
7159 (IS_SCHEMA(child, "choice")) ||
7160 (IS_SCHEMA(child, "sequence"))) {
7161 subtype = NULL;
7162 if (IS_SCHEMA(child, "element")) {
7163 subtype = (xmlSchemaTypePtr)
7164 xmlSchemaParseElement(ctxt, schema, child, 0);
7165 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007166 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007167 } else if (IS_SCHEMA(child, "any")) {
7168 subtype = xmlSchemaParseAny(ctxt, schema, child);
7169 } else if (IS_SCHEMA(child, "sequence")) {
7170 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7171 } else if (IS_SCHEMA(child, "choice")) {
7172 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7173 }
7174 if (subtype != NULL) {
7175 if (last == NULL) {
7176 type->subtypes = subtype;
7177 last = subtype;
7178 } else {
7179 last->next = subtype;
7180 last = subtype;
7181 }
7182 last->next = NULL;
7183 }
7184 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007185 }
7186 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007187 /* TODO: error code. */
7188 xmlSchemaPContentErr(ctxt,
7189 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7190 NULL, type, node, child, NULL,
7191 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007192 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007193 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007194 return (type);
7195}
7196
7197/**
7198 * xmlSchemaParseSequence:
7199 * @ctxt: a schema validation context
7200 * @schema: the schema being built
7201 * @node: a subtree containing XML Schema informations
7202 *
7203 * parse a XML schema Sequence definition
7204 * *WARNING* this interface is highly subject to change
7205 *
William M. Bracke7091952004-05-11 15:09:58 +00007206 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007207 * 1 in case of success.
7208 */
7209static xmlSchemaTypePtr
7210xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007211 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007212{
7213 xmlSchemaTypePtr type, subtype, last = NULL;
7214 xmlNodePtr child = NULL;
7215 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007216 xmlAttrPtr attr;
7217 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007218
7219 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7220 return (NULL);
7221
William M. Brack2f2a6632004-08-20 23:09:47 +00007222 oldcontainer = ctxt->container;
7223 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7224 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007225 if (type == NULL)
7226 return (NULL);
7227 type->node = node;
7228 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007229 /*
7230 * Check for illegal attributes.
7231 */
7232 attr = node->properties;
7233 while (attr != NULL) {
7234 if (attr->ns == NULL) {
7235 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7236 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7237 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7238 xmlSchemaPIllegalAttrErr(ctxt,
7239 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7240 NULL, type, attr);
7241 }
7242 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7243 xmlSchemaPIllegalAttrErr(ctxt,
7244 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7245 NULL, type, attr);
7246 }
7247 attr = attr->next;
7248 }
7249 /*
7250 * Extract and validate attributes.
7251 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007252 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007253 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7254 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7255 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007256 /*
7257 * And now for the children...
7258 */
7259 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007260 child = node->children;
7261 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007262 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7263 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007264 }
7265 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007266 (IS_SCHEMA(child, "group")) ||
7267 (IS_SCHEMA(child, "any")) ||
7268 (IS_SCHEMA(child, "choice")) ||
7269 (IS_SCHEMA(child, "sequence"))) {
7270 subtype = NULL;
7271 if (IS_SCHEMA(child, "element")) {
7272 subtype = (xmlSchemaTypePtr)
7273 xmlSchemaParseElement(ctxt, schema, child, 0);
7274 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007275 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007276 } else if (IS_SCHEMA(child, "any")) {
7277 subtype = xmlSchemaParseAny(ctxt, schema, child);
7278 } else if (IS_SCHEMA(child, "choice")) {
7279 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7280 } else if (IS_SCHEMA(child, "sequence")) {
7281 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7282 }
7283 if (subtype != NULL) {
7284 if (last == NULL) {
7285 type->subtypes = subtype;
7286 last = subtype;
7287 } else {
7288 last->next = subtype;
7289 last = subtype;
7290 }
7291 last->next = NULL;
7292 }
7293 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007294 }
7295 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007296 xmlSchemaPContentErr(ctxt,
7297 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7298 NULL, type, node, child, NULL,
7299 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007300 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007301 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007302
7303 return (type);
7304}
7305
7306/**
7307 * xmlSchemaParseRestriction:
7308 * @ctxt: a schema validation context
7309 * @schema: the schema being built
7310 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007311 *
7312 * parse a XML schema Restriction definition
7313 * *WARNING* this interface is highly subject to change
7314 *
7315 * Returns the type definition or NULL in case of error
7316 */
7317static xmlSchemaTypePtr
7318xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007319 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007320{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007321 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007322 xmlNodePtr child = NULL;
7323 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007324 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007325 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007326
7327 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7328 return (NULL);
7329
7330 oldcontainer = ctxt->container;
7331
William M. Brack2f2a6632004-08-20 23:09:47 +00007332 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7333 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007334 if (type == NULL)
7335 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007336 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007337 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007338 /*
7339 * Check for illegal attributes.
7340 */
7341 attr = node->properties;
7342 while (attr != NULL) {
7343 if (attr->ns == NULL) {
7344 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7345 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7346 xmlSchemaPIllegalAttrErr(ctxt,
7347 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7348 NULL, type, attr);
7349 }
7350 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7351 xmlSchemaPIllegalAttrErr(ctxt,
7352 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7353 NULL, type, attr);
7354 }
7355 attr = attr->next;
7356 }
7357 /*
7358 * Extract and validate attributes.
7359 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007360 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007361 /*
7362 * Attribute "base".
7363 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007364 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007365 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007366 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7367 /* TODO: Think about the error code. */
7368 xmlSchemaPMissingAttrErr(ctxt,
7369 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7370 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007371 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007372 /*
7373 * And now for the children...
7374 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007375 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007376 child = node->children;
7377 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007378 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7379 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007380 }
7381 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007382 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7383 if (IS_SCHEMA(child, "all")) {
7384 subtype = (xmlSchemaTypePtr)
7385 xmlSchemaParseAll(ctxt, schema, child);
7386 child = child->next;
7387 type->subtypes = subtype;
7388 } else if (IS_SCHEMA(child, "choice")) {
7389 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7390 child = child->next;
7391 type->subtypes = subtype;
7392 } else if (IS_SCHEMA(child, "sequence")) {
7393 subtype = (xmlSchemaTypePtr)
7394 xmlSchemaParseSequence(ctxt, schema, child);
7395 child = child->next;
7396 type->subtypes = subtype;
7397 } else if (IS_SCHEMA(child, "group")) {
7398 subtype = (xmlSchemaTypePtr)
7399 xmlSchemaParseGroup(ctxt, schema, child, 0);
7400 child = child->next;
7401 type->subtypes = subtype;
7402 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007403 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7404 if (IS_SCHEMA(child, "simpleType")) {
7405 if (type->base != NULL) {
7406 /*
7407 * src-restriction-base-or-simpleType
7408 * Either the base [attribute] or the simpleType [child] of the
7409 * <restriction> element must be present, but not both.
7410 */
7411 xmlSchemaPContentErr(ctxt,
7412 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7413 NULL, NULL, type->node, child,
7414 "The attribute 'base' and the <simpleType> child are "
7415 "mutually exclusive", NULL);
7416 } else {
7417 subtype = (xmlSchemaTypePtr)
7418 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7419 type->baseType = subtype;
7420 }
7421 child = child->next;
7422 }
7423 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007424 if (IS_SCHEMA(child, "simpleType")) {
7425 subtype = (xmlSchemaTypePtr)
7426 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007427 type->subtypes = subtype;
7428 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007429 }
7430 }
7431 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7432 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7433 xmlSchemaFacetPtr facet, lastfacet = NULL;
7434
Daniel Veillard01fa6152004-06-29 17:04:39 +00007435 /*
7436 * Add the facets to the parent simpleType/complexType.
7437 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007438 /*
7439 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7440 * Simple Type Definition Schema Representation Constraint:
7441 * *Single Facet Value*
7442 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007443 while ((IS_SCHEMA(child, "minInclusive")) ||
7444 (IS_SCHEMA(child, "minExclusive")) ||
7445 (IS_SCHEMA(child, "maxInclusive")) ||
7446 (IS_SCHEMA(child, "maxExclusive")) ||
7447 (IS_SCHEMA(child, "totalDigits")) ||
7448 (IS_SCHEMA(child, "fractionDigits")) ||
7449 (IS_SCHEMA(child, "pattern")) ||
7450 (IS_SCHEMA(child, "enumeration")) ||
7451 (IS_SCHEMA(child, "whiteSpace")) ||
7452 (IS_SCHEMA(child, "length")) ||
7453 (IS_SCHEMA(child, "maxLength")) ||
7454 (IS_SCHEMA(child, "minLength"))) {
7455 facet = xmlSchemaParseFacet(ctxt, schema, child);
7456 if (facet != NULL) {
7457 if (lastfacet == NULL)
7458 ctxt->ctxtType->facets = facet;
7459 else
7460 lastfacet->next = facet;
7461 lastfacet = facet;
7462 lastfacet->next = NULL;
7463 }
7464 child = child->next;
7465 }
7466 /*
7467 * Create links for derivation and validation.
7468 */
7469 if (lastfacet != NULL) {
7470 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7471
7472 facet = ctxt->ctxtType->facets;
7473 do {
7474 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7475 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007476 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007477 xmlFree(facetLink);
7478 return (NULL);
7479 }
7480 facetLink->facet = facet;
7481 facetLink->next = NULL;
7482 if (lastFacetLink == NULL)
7483 ctxt->ctxtType->facetSet = facetLink;
7484 else
7485 lastFacetLink->next = facetLink;
7486 lastFacetLink = facetLink;
7487 facet = facet->next;
7488 } while (facet != NULL);
7489 }
7490 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007491 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7492 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7493 if (IS_SCHEMA(child, "anyAttribute")) {
7494 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7495 child = child->next;
7496 }
7497 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007498 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007499 /* TODO: Think about the error code. */
7500 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7501 xmlSchemaPContentErr(ctxt,
7502 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7503 NULL, type, node, child, NULL,
7504 "annotation?, (group | all | choice | sequence)?, "
7505 "((attribute | attributeGroup)*, anyAttribute?))");
7506 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7507 xmlSchemaPContentErr(ctxt,
7508 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7509 NULL, type, node, child, NULL,
7510 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7511 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7512 "length | minLength | maxLength | enumeration | whiteSpace | "
7513 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7514 } else {
7515 /* Simple type */
7516 xmlSchemaPContentErr(ctxt,
7517 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7518 NULL, type, node, child, NULL,
7519 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7520 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7521 "length | minLength | maxLength | enumeration | whiteSpace | "
7522 "pattern)*))");
7523 }
7524 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007525 ctxt->container = oldcontainer;
7526 return (type);
7527}
7528
7529/**
7530 * xmlSchemaParseExtension:
7531 * @ctxt: a schema validation context
7532 * @schema: the schema being built
7533 * @node: a subtree containing XML Schema informations
7534 *
7535 * parse a XML schema Extension definition
7536 * *WARNING* this interface is highly subject to change
7537 *
7538 * Returns the type definition or NULL in case of error
7539 */
7540static xmlSchemaTypePtr
7541xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007542 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007543{
7544 xmlSchemaTypePtr type, subtype;
7545 xmlNodePtr child = NULL;
7546 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007547 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007548
7549 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7550 return (NULL);
7551
7552 oldcontainer = ctxt->container;
7553
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007554 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007555 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007556 if (type == NULL)
7557 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007558 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007559 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007560 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007561 ctxt->container = name;
7562
7563 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7564 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007565 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007566 "<extension>: The attribute \"base\" is missing.\n",
7567 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007568 }
7569 child = node->children;
7570 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007571 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7572 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007573 }
7574 subtype = NULL;
7575
7576 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007577 subtype = xmlSchemaParseAll(ctxt, schema, child);
7578 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007579 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007580 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7581 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007582 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007583 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7584 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007585 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007586 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007587 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007588 }
7589 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007590 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007591 if ((ctxt->ctxtType != NULL) &&
7592 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7593 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7594 if (IS_SCHEMA(child, "anyAttribute")) {
7595 ctxt->ctxtType->attributeWildcard =
7596 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7597 child = child->next;
7598 }
7599 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007600 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007601 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7603 "<extension> has unexpected content.\n", type->name,
7604 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007605 }
7606 ctxt->container = oldcontainer;
7607 return (type);
7608}
7609
7610/**
7611 * xmlSchemaParseSimpleContent:
7612 * @ctxt: a schema validation context
7613 * @schema: the schema being built
7614 * @node: a subtree containing XML Schema informations
7615 *
7616 * parse a XML schema SimpleContent definition
7617 * *WARNING* this interface is highly subject to change
7618 *
7619 * Returns the type definition or NULL in case of error
7620 */
7621static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007622xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7623 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007624{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007625 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007626 xmlNodePtr child = NULL;
7627 xmlChar name[30];
7628
7629 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7630 return (NULL);
7631
William M. Bracke7091952004-05-11 15:09:58 +00007632 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007633 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007634 if (type == NULL)
7635 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007636 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007637 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007638 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007639
7640 child = node->children;
7641 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007642 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7643 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007644 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007645 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007646 ctxt->parentItem = type;
7647 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007648 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007649 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007650 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007651 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007652 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007653 subtype = (xmlSchemaTypePtr)
7654 xmlSchemaParseExtension(ctxt, schema, child);
7655 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007656 }
7657 type->subtypes = subtype;
7658 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007659 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007660 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7661 "<simpleContent> has unexpected content.\n",
7662 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007663 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007664 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007665 return (type);
7666}
7667
7668/**
7669 * xmlSchemaParseComplexContent:
7670 * @ctxt: a schema validation context
7671 * @schema: the schema being built
7672 * @node: a subtree containing XML Schema informations
7673 *
7674 * parse a XML schema ComplexContent definition
7675 * *WARNING* this interface is highly subject to change
7676 *
7677 * Returns the type definition or NULL in case of error
7678 */
7679static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007680xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7681 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007682{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007683 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007684 xmlNodePtr child = NULL;
7685 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007686 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007687
7688 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7689 return (NULL);
7690
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007691 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007692 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007693 if (type == NULL)
7694 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007695 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007696 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007697 /*
7698 * Check for illegal attributes.
7699 */
7700 attr = node->properties;
7701 while (attr != NULL) {
7702 if (attr->ns == NULL) {
7703 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7704 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7705 {
7706 xmlSchemaPIllegalAttrErr(ctxt,
7707 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7708 NULL, NULL, attr);
7709 }
7710 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7711 xmlSchemaPIllegalAttrErr(ctxt,
7712 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7713 NULL, NULL, attr);
7714 }
7715 attr = attr->next;
7716 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007717 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007718 /*
7719 * Handle attribute 'mixed'.
7720 */
7721 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7722 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7723 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7724 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007725 child = node->children;
7726 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007727 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7728 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007729 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007730 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007731 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007732 subtype = NULL;
7733 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007734 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007735 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007736 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007737 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007738 subtype = (xmlSchemaTypePtr)
7739 xmlSchemaParseExtension(ctxt, schema, child);
7740 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007741 }
7742 type->subtypes = subtype;
7743 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007744 xmlSchemaPContentErr(ctxt,
7745 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7746 NULL, NULL, node, child,
7747 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007748 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007749 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007750 return (type);
7751}
7752
7753/**
7754 * xmlSchemaParseComplexType:
7755 * @ctxt: a schema validation context
7756 * @schema: the schema being built
7757 * @node: a subtree containing XML Schema informations
7758 *
7759 * parse a XML schema Complex Type definition
7760 * *WARNING* this interface is highly subject to change
7761 *
7762 * Returns the type definition or NULL in case of error
7763 */
7764static xmlSchemaTypePtr
7765xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007766 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007767{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007768 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007769 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007770 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007771 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007772 xmlAttrPtr attr;
7773 const xmlChar *attrValue;
7774 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007775 char buf[40];
7776
Daniel Veillard4255d502002-04-16 15:50:10 +00007777
7778 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7779 return (NULL);
7780
Daniel Veillard01fa6152004-06-29 17:04:39 +00007781 ctxtType = ctxt->ctxtType;
7782
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007783 if (topLevel) {
7784 attr = xmlSchemaGetPropNode(node, "name");
7785 if (attr == NULL) {
7786 xmlSchemaPMissingAttrErr(ctxt,
7787 XML_SCHEMAP_S4S_ATTR_MISSING,
7788 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7789 "name", NULL);
7790 return (NULL);
7791 } else if (xmlSchemaPValAttrNode(ctxt,
7792 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7793 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7794 return (NULL);
7795 }
7796 }
7797
7798 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007799 /*
7800 * Parse as local complex type definition.
7801 */
7802 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7803 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7804 if (type == NULL)
7805 return (NULL);
7806 name = (const xmlChar *) buf;
7807 type->node = node;
7808 type->type = XML_SCHEMA_TYPE_COMPLEX;
7809 /*
7810 * TODO: We need the target namespace.
7811 */
7812 } else {
7813 /*
7814 * Parse as global complex type definition.
7815 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007816 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007817 if (type == NULL)
7818 return (NULL);
7819 type->node = node;
7820 type->type = XML_SCHEMA_TYPE_COMPLEX;
7821 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7822 /*
7823 * Set defaults.
7824 */
7825 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7826 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
7827 }
7828 /*
7829 * Handle attributes.
7830 */
7831 attr = node->properties;
7832 while (attr != NULL) {
7833 if (attr->ns == NULL) {
7834 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7835 /*
7836 * Attribute "id".
7837 */
7838 type->id = xmlSchemaGetProp(ctxt, node, "id");
7839 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
7840 /*
7841 * Attribute "mixed".
7842 */
7843 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7844 (xmlNodePtr) attr))
7845 type->flags |= XML_SCHEMAS_TYPE_MIXED;
7846 } else if (topLevel) {
7847 /*
7848 * Attributes of global complex type definitions.
7849 */
7850 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7851 /* Pass. */
7852 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
7853 /*
7854 * Attribute "abstract".
7855 */
7856 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7857 (xmlNodePtr) attr))
7858 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
7859 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
7860 /*
7861 * Attribute "final".
7862 */
7863 attrValue = xmlSchemaGetNodeContent(ctxt,
7864 (xmlNodePtr) attr);
7865 if (xmlSchemaPValAttrBlockFinal(attrValue,
7866 &(type->flags),
7867 -1,
7868 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
7869 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
7870 -1, -1, -1) != 0)
7871 {
7872 xmlSchemaPSimpleTypeErr(ctxt,
7873 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7874 &des, type, (xmlNodePtr) attr,
7875 NULL,
7876 "(#all | List of (extension | restriction))",
7877 attrValue, NULL, NULL, NULL);
7878 }
7879 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
7880 /*
7881 * Attribute "block".
7882 */
7883 attrValue = xmlSchemaGetNodeContent(ctxt,
7884 (xmlNodePtr) attr);
7885 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7886 -1,
7887 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
7888 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
7889 -1, -1, -1) != 0) {
7890 xmlSchemaPSimpleTypeErr(ctxt,
7891 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7892 &des, type, (xmlNodePtr) attr,
7893 NULL,
7894 "(#all | List of (extension | restriction)) ",
7895 attrValue, NULL, NULL, NULL);
7896 }
7897 } else {
7898 xmlSchemaPIllegalAttrErr(ctxt,
7899 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7900 &des, type, attr);
7901 }
7902 } else {
7903 xmlSchemaPIllegalAttrErr(ctxt,
7904 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7905 &des, type, attr);
7906 }
7907 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7908 xmlSchemaPIllegalAttrErr(ctxt,
7909 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7910 &des, type, attr);
7911 }
7912 attr = attr->next;
7913 }
7914 /*
7915 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007916 * This will be only changed if a complex type
7917 * inherits an attribute wildcard from a base type.
7918 */
7919 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007920 /*
7921 * And now for the children...
7922 */
7923 oldcontainer = ctxt->container;
7924 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007925 child = node->children;
7926 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007927 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7928 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007929 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007930 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007931 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007932 /*
7933 * 3.4.3 : 2.2
7934 * Specifying mixed='true' when the <simpleContent>
7935 * alternative is chosen has no effect
7936 */
William M. Bracke7091952004-05-11 15:09:58 +00007937 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7938 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007939 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7940 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007941 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007942 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7943 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007944 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007945 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007946 /*
7947 * Parse model groups.
7948 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007949 if (IS_SCHEMA(child, "all")) {
7950 subtype = xmlSchemaParseAll(ctxt, schema, child);
7951 child = child->next;
7952 } else if (IS_SCHEMA(child, "choice")) {
7953 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7954 child = child->next;
7955 } else if (IS_SCHEMA(child, "sequence")) {
7956 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7957 child = child->next;
7958 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007959 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007960 child = child->next;
7961 }
7962 if (subtype != NULL)
7963 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007964 /*
7965 * Parse attribute decls/refs.
7966 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007967 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007968 /*
7969 * Parse attribute wildcard.
7970 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007971 if (IS_SCHEMA(child, "anyAttribute")) {
7972 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7973 child = child->next;
7974 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007975 }
7976 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007977 xmlSchemaPContentErr(ctxt,
7978 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7979 &des, type, node, child,
7980 NULL, "(annotation?, (simpleContent | complexContent | "
7981 "((group | all | choice | sequence)?, ((attribute | "
7982 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007983 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007984 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00007985 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007986 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007987 return (type);
7988}
7989
Daniel Veillard4255d502002-04-16 15:50:10 +00007990/**
7991 * xmlSchemaParseSchema:
7992 * @ctxt: a schema validation context
7993 * @node: a subtree containing XML Schema informations
7994 *
7995 * parse a XML schema definition from a node set
7996 * *WARNING* this interface is highly subject to change
7997 *
7998 * Returns the internal XML Schema structure built from the resource or
7999 * NULL in case of error
8000 */
8001static xmlSchemaPtr
8002xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8003{
8004 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008005 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008006 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008007 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008008
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008009 /*
8010 * This one is called by xmlSchemaParse only and is used if
8011 * the schema to be parsed was specified via the API; i.e. not
8012 * automatically by the validated instance document.
8013 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008014 if ((ctxt == NULL) || (node == NULL))
8015 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008016 nberrors = ctxt->nberrors;
8017 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008018 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008019 xmlSchemaImportPtr import;
8020
Daniel Veillard4255d502002-04-16 15:50:10 +00008021 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008022 if (schema == NULL)
8023 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008024 /*
8025 * Disable build of list of items.
8026 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008027 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8028 if (attr != NULL) {
8029 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8030 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8031 /*
8032 * TODO: Should we proceed with an invalid target namespace?
8033 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008034 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8035 } else {
8036 schema->targetNamespace = NULL;
8037 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008038 /*
8039 * Add the current ns name and location to the import table;
8040 * this is needed to have a consistent mechanism, regardless
8041 * if all schemata are constructed dynamically fired by the
8042 * instance or if the schema to be used was specified via
8043 * the API.
8044 */
8045 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8046 schema->targetNamespace);
8047 if (import == NULL) {
8048 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8049 NULL, NULL, (xmlNodePtr) ctxt->doc,
8050 "Internal error: xmlSchemaParseSchema, "
8051 "failed to add an import entry", NULL);
8052 xmlSchemaFree(schema);
8053 schema = NULL;
8054 return (NULL);
8055 }
8056 import->schemaLocation = ctxt->URL;
8057 /*
8058 * NOTE: We won't set the doc here, otherwise it will be freed
8059 * if the import struct is freed.
8060 * import->doc = ctxt->doc;
8061 */
8062
Daniel Veillardc0826a72004-08-10 14:17:33 +00008063 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008064 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008065 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8066 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8067
William M. Brack2f2a6632004-08-20 23:09:47 +00008068 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008069 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8070 } else {
8071 xmlDocPtr doc;
8072
8073 doc = node->doc;
8074
8075 if ((doc != NULL) && (doc->URL != NULL)) {
8076 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8077 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008078 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008079 } else {
8080 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8081 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008082 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008083 }
8084 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008085 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008086 if (ctxt->nberrors != 0) {
8087 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008088 xmlSchemaFree(schema);
8089 schema = NULL;
8090 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008091 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008092 if (schema != NULL)
8093 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008094 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008095#ifdef DEBUG
8096 if (schema == NULL)
8097 xmlGenericError(xmlGenericErrorContext,
8098 "xmlSchemaParse() failed\n");
8099#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008100 return (schema);
8101}
8102
8103/************************************************************************
8104 * *
8105 * Validating using Schemas *
8106 * *
8107 ************************************************************************/
8108
8109/************************************************************************
8110 * *
8111 * Reading/Writing Schemas *
8112 * *
8113 ************************************************************************/
8114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008115#if 0 /* Will be enabled if it is clear what options are needed. */
8116/**
8117 * xmlSchemaParserCtxtSetOptions:
8118 * @ctxt: a schema parser context
8119 * @options: a combination of xmlSchemaParserOption
8120 *
8121 * Sets the options to be used during the parse.
8122 *
8123 * Returns 0 in case of success, -1 in case of an
8124 * API error.
8125 */
8126static int
8127xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8128 int options)
8129
8130{
8131 int i;
8132
8133 if (ctxt == NULL)
8134 return (-1);
8135 /*
8136 * WARNING: Change the start value if adding to the
8137 * xmlSchemaParseOption.
8138 */
8139 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8140 if (options & 1<<i) {
8141 return (-1);
8142 }
8143 }
8144 ctxt->options = options;
8145 return (0);
8146}
8147
8148/**
8149 * xmlSchemaValidCtxtGetOptions:
8150 * @ctxt: a schema parser context
8151 *
8152 * Returns the option combination of the parser context.
8153 */
8154static int
8155xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8156
8157{
8158 if (ctxt == NULL)
8159 return (-1);
8160 else
8161 return (ctxt->options);
8162}
8163
8164 void *curItems; /* used for dynamic addition of schemata */
8165 int nbCurItems; /* used for dynamic addition of schemata */
8166 int sizeCurItems; /* used for dynamic addition of schemata */
8167
8168#endif
8169
Daniel Veillard4255d502002-04-16 15:50:10 +00008170/**
8171 * xmlSchemaNewParserCtxt:
8172 * @URL: the location of the schema
8173 *
8174 * Create an XML Schemas parse context for that file/resource expected
8175 * to contain an XML Schemas file.
8176 *
8177 * Returns the parser context or NULL in case of error
8178 */
8179xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008180xmlSchemaNewParserCtxt(const char *URL)
8181{
Daniel Veillard4255d502002-04-16 15:50:10 +00008182 xmlSchemaParserCtxtPtr ret;
8183
8184 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008185 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008186
8187 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8188 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008189 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008190 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008191 return (NULL);
8192 }
8193 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008194 ret->dict = xmlDictCreate();
8195 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008196 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008197 return (ret);
8198}
8199
8200/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008201 * xmlSchemaNewParserCtxtUseDict:
8202 * @URL: the location of the schema
8203 * @dict: the dictionary to be used
8204 *
8205 * Create an XML Schemas parse context for that file/resource expected
8206 * to contain an XML Schemas file.
8207 *
8208 * Returns the parser context or NULL in case of error
8209 */
8210static xmlSchemaParserCtxtPtr
8211xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8212{
8213 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008214 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008215 if (URL == NULL)
8216 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008217 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008218
8219 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8220 if (ret == NULL) {
8221 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8222 NULL);
8223 return (NULL);
8224 }
8225 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8226 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008227 xmlDictReference(dict);
8228 if (URL != NULL)
8229 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008230 ret->includes = 0;
8231 return (ret);
8232}
8233
8234
8235/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008236 * xmlSchemaNewMemParserCtxt:
8237 * @buffer: a pointer to a char array containing the schemas
8238 * @size: the size of the array
8239 *
8240 * Create an XML Schemas parse context for that memory buffer expected
8241 * to contain an XML Schemas file.
8242 *
8243 * Returns the parser context or NULL in case of error
8244 */
8245xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008246xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8247{
Daniel Veillard6045c902002-10-09 21:13:59 +00008248 xmlSchemaParserCtxtPtr ret;
8249
8250 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008251 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008252
8253 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8254 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008255 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008256 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008257 return (NULL);
8258 }
8259 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8260 ret->buffer = buffer;
8261 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008262 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008263 return (ret);
8264}
8265
8266/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008267 * xmlSchemaNewDocParserCtxt:
8268 * @doc: a preparsed document tree
8269 *
8270 * Create an XML Schemas parse context for that document.
8271 * NB. The document may be modified during the parsing process.
8272 *
8273 * Returns the parser context or NULL in case of error
8274 */
8275xmlSchemaParserCtxtPtr
8276xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8277{
8278 xmlSchemaParserCtxtPtr ret;
8279
8280 if (doc == NULL)
8281 return (NULL);
8282
8283 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8284 if (ret == NULL) {
8285 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8286 NULL);
8287 return (NULL);
8288 }
8289 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8290 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008291 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008292 /* The application has responsibility for the document */
8293 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008294
8295 return (ret);
8296}
8297
8298/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008299 * xmlSchemaFreeParserCtxt:
8300 * @ctxt: the schema parser context
8301 *
8302 * Free the resources associated to the schema parser context
8303 */
8304void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008305xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8306{
Daniel Veillard4255d502002-04-16 15:50:10 +00008307 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008308 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008309 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008310 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008311 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008312 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008313 xmlFree(ctxt->assemble);
8314 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008315 if (ctxt->vctxt != NULL) {
8316 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8317 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008318 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008319 xmlFree(ctxt);
8320}
8321
8322/************************************************************************
8323 * *
8324 * Building the content models *
8325 * *
8326 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008327
Daniel Veillard4255d502002-04-16 15:50:10 +00008328/**
8329 * xmlSchemaBuildAContentModel:
8330 * @type: the schema type definition
8331 * @ctxt: the schema parser context
8332 * @name: the element name whose content is being built
8333 *
8334 * Generate the automata sequence needed for that type
8335 */
8336static void
8337xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008338 xmlSchemaParserCtxtPtr ctxt,
8339 const xmlChar * name)
8340{
Daniel Veillard4255d502002-04-16 15:50:10 +00008341 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008342 xmlGenericError(xmlGenericErrorContext,
8343 "Found unexpected type = NULL in %s content model\n",
8344 name);
8345 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008346 }
8347 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008348 case XML_SCHEMA_TYPE_ANY: {
8349 xmlAutomataStatePtr start, end;
8350 xmlSchemaWildcardPtr wild;
8351 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008352
Daniel Veillardc0826a72004-08-10 14:17:33 +00008353 wild = type->attributeWildcard;
8354
8355 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008356 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008357 "Internal error: xmlSchemaBuildAContentModel, "
8358 "no wildcard on xsd:any.\n", NULL, NULL);
8359 return;
8360 }
8361
8362 start = ctxt->state;
8363 end = xmlAutomataNewState(ctxt->am);
8364
8365 if (type->maxOccurs == 1) {
8366 if (wild->any == 1) {
8367 /*
8368 * We need to add both transitions:
8369 *
8370 * 1. the {"*", "*"} for elements in a namespace.
8371 */
8372 ctxt->state =
8373 xmlAutomataNewTransition2(ctxt->am,
8374 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8375 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8376 /*
8377 * 2. the {"*"} for elements in no namespace.
8378 */
8379 ctxt->state =
8380 xmlAutomataNewTransition2(ctxt->am,
8381 start, NULL, BAD_CAST "*", NULL, type);
8382 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8383
8384 } else if (wild->nsSet != NULL) {
8385 ns = wild->nsSet;
8386 do {
8387 ctxt->state = start;
8388 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8389 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8390 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8391 ns = ns->next;
8392 } while (ns != NULL);
8393
8394 } else if (wild->negNsSet != NULL) {
8395 xmlAutomataStatePtr deadEnd;
8396
8397 deadEnd = xmlAutomataNewState(ctxt->am);
8398 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8399 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8400 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8401 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8402 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8403 }
8404 } else {
8405 int counter;
8406 xmlAutomataStatePtr hop;
8407 int maxOccurs =
8408 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8409 int minOccurs =
8410 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8411
8412 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8413 hop = xmlAutomataNewState(ctxt->am);
8414 if (wild->any == 1) {
8415 ctxt->state =
8416 xmlAutomataNewTransition2(ctxt->am,
8417 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8418 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8419 ctxt->state =
8420 xmlAutomataNewTransition2(ctxt->am,
8421 start, NULL, BAD_CAST "*", NULL, type);
8422 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8423 } else if (wild->nsSet != NULL) {
8424 ns = wild->nsSet;
8425 do {
8426 ctxt->state =
8427 xmlAutomataNewTransition2(ctxt->am,
8428 start, NULL, BAD_CAST "*", ns->value, type);
8429 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8430 ns = ns->next;
8431 } while (ns != NULL);
8432
8433 } else if (wild->negNsSet != NULL) {
8434 xmlAutomataStatePtr deadEnd;
8435
8436 deadEnd = xmlAutomataNewState(ctxt->am);
8437 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8438 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8439 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8440 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8441 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8442 }
8443 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8444 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8445 }
8446 if (type->minOccurs == 0) {
8447 xmlAutomataNewEpsilon(ctxt->am, start, end);
8448 }
8449 ctxt->state = end;
8450 break;
8451 }
8452 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008453 xmlAutomataStatePtr oldstate;
8454 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008455
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008456 /*
8457 * IMPORTANT: This puts element declarations
8458 * (and never element decl. references) into the
8459 * automaton. This is crucial and should not be changed,
8460 * since validating functions rely now on it.
8461 */
8462 particle = (xmlSchemaElementPtr) type;
8463 if (particle->ref != NULL) {
8464 if (particle->refDecl == NULL) {
8465 /*
8466 * Skip content model creation if the reference
8467 * did not resolve to a declaration.
8468 */
8469 break;
8470 } else {
8471 /*
8472 * Referenced global element declaration.
8473 */
8474 elemDecl = particle->refDecl;
8475 }
8476 } else {
8477 /*
8478 * Anonymous element declaration.
8479 */
8480 elemDecl = particle;
8481 }
8482
8483 oldstate = ctxt->state;
8484
8485 if (particle->maxOccurs >= UNBOUNDED) {
8486 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008487 xmlAutomataStatePtr tmp;
8488 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008489
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008490 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008491 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008492 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008493 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008494 particle->minOccurs - 1, UNBOUNDED);
8495 ctxt->state =
8496 xmlAutomataNewTransition2(ctxt->am,
8497 ctxt->state, NULL,
8498 elemDecl->name,
8499 elemDecl->targetNamespace,
8500 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008501 tmp = ctxt->state;
8502 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008503 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008504 ctxt->state =
8505 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008506 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008507
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008508 } else {
8509 ctxt->state =
8510 xmlAutomataNewTransition2(ctxt->am,
8511 ctxt->state, NULL,
8512 elemDecl->name,
8513 elemDecl->targetNamespace,
8514 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008515 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8516 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008517 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008518 /* basically an elem* */
8519 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8520 ctxt->state);
8521 }
8522 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008523 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008524 xmlAutomataStatePtr tmp;
8525 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008526
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008527 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8528 oldstate, NULL);
8529 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008530 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008531 particle->minOccurs - 1,
8532 particle->maxOccurs - 1);
8533 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8534 ctxt->state,
8535 NULL,
8536 elemDecl->name,
8537 elemDecl->targetNamespace,
8538 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008539 tmp = ctxt->state;
8540 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008541 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008542 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008543 NULL, counter);
8544 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008545 /* basically an elem? */
8546 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008547 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008548 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008549
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008550 } else {
8551 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8552 ctxt->state,
8553 NULL,
8554 elemDecl->name,
8555 elemDecl->targetNamespace,
8556 (xmlSchemaTypePtr) elemDecl);
8557 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008558 /* basically an elem? */
8559 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008560 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008561 }
8562 }
8563 break;
8564 }
8565 case XML_SCHEMA_TYPE_SEQUENCE:{
8566 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008567
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008568 /*
8569 * If max and min occurances are default (1) then
8570 * simply iterate over the subtypes
8571 */
8572 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8573 subtypes = type->subtypes;
8574 while (subtypes != NULL) {
8575 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8576 subtypes = subtypes->next;
8577 }
8578 } else {
8579 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008580
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008581 if (type->maxOccurs >= UNBOUNDED) {
8582 if (type->minOccurs > 1) {
8583 xmlAutomataStatePtr tmp;
8584 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008585
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008586 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8587 oldstate,
8588 NULL);
8589 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008590
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008591 counter = xmlAutomataNewCounter(ctxt->am,
8592 type->
8593 minOccurs - 1,
8594 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008595
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008596 subtypes = type->subtypes;
8597 while (subtypes != NULL) {
8598 xmlSchemaBuildAContentModel(subtypes, ctxt,
8599 name);
8600 subtypes = subtypes->next;
8601 }
8602 tmp = ctxt->state;
8603 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8604 oldstate, counter);
8605 ctxt->state =
8606 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8607 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008608
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008609 } else {
8610 subtypes = type->subtypes;
8611 while (subtypes != NULL) {
8612 xmlSchemaBuildAContentModel(subtypes, ctxt,
8613 name);
8614 subtypes = subtypes->next;
8615 }
8616 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8617 oldstate);
8618 if (type->minOccurs == 0) {
8619 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8620 ctxt->state);
8621 }
8622 }
8623 } else if ((type->maxOccurs > 1)
8624 || (type->minOccurs > 1)) {
8625 xmlAutomataStatePtr tmp;
8626 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008627
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008628 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8629 oldstate,
8630 NULL);
8631 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008632
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008633 counter = xmlAutomataNewCounter(ctxt->am,
8634 type->minOccurs -
8635 1,
8636 type->maxOccurs -
8637 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008638
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008639 subtypes = type->subtypes;
8640 while (subtypes != NULL) {
8641 xmlSchemaBuildAContentModel(subtypes, ctxt,
8642 name);
8643 subtypes = subtypes->next;
8644 }
8645 tmp = ctxt->state;
8646 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8647 counter);
8648 ctxt->state =
8649 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8650 counter);
8651 if (type->minOccurs == 0) {
8652 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8653 ctxt->state);
8654 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008655
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008656 } else {
8657 subtypes = type->subtypes;
8658 while (subtypes != NULL) {
8659 xmlSchemaBuildAContentModel(subtypes, ctxt,
8660 name);
8661 subtypes = subtypes->next;
8662 }
8663 if (type->minOccurs == 0) {
8664 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8665 ctxt->state);
8666 }
8667 }
8668 }
8669 break;
8670 }
8671 case XML_SCHEMA_TYPE_CHOICE:{
8672 xmlSchemaTypePtr subtypes;
8673 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008674
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008675 start = ctxt->state;
8676 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008677
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008678 /*
8679 * iterate over the subtypes and remerge the end with an
8680 * epsilon transition
8681 */
8682 if (type->maxOccurs == 1) {
8683 subtypes = type->subtypes;
8684 while (subtypes != NULL) {
8685 ctxt->state = start;
8686 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8687 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8688 subtypes = subtypes->next;
8689 }
8690 } else {
8691 int counter;
8692 xmlAutomataStatePtr hop;
8693 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8694 UNBOUNDED : type->maxOccurs - 1;
8695 int minOccurs =
8696 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008697
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008698 /*
8699 * use a counter to keep track of the number of transtions
8700 * which went through the choice.
8701 */
8702 counter =
8703 xmlAutomataNewCounter(ctxt->am, minOccurs,
8704 maxOccurs);
8705 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008707 subtypes = type->subtypes;
8708 while (subtypes != NULL) {
8709 ctxt->state = start;
8710 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8711 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8712 subtypes = subtypes->next;
8713 }
8714 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8715 counter);
8716 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8717 counter);
8718 }
8719 if (type->minOccurs == 0) {
8720 xmlAutomataNewEpsilon(ctxt->am, start, end);
8721 }
8722 ctxt->state = end;
8723 break;
8724 }
8725 case XML_SCHEMA_TYPE_ALL:{
8726 xmlAutomataStatePtr start;
8727 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008728
Daniel Veillard3646d642004-06-02 19:19:14 +00008729 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008730 int lax;
8731
8732 subtypes = type->subtypes;
8733 if (subtypes == NULL)
8734 break;
8735 start = ctxt->state;
8736 while (subtypes != NULL) {
8737 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008738 /*
8739 * the following 'if' was needed to fix bug 139897
8740 * not quite sure why it only needs to be done for
8741 * elements with a 'ref', but it seems to work ok.
8742 */
8743 if (subtypes->ref != NULL)
8744 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008745 elem = (xmlSchemaElementPtr) subtypes;
8746 /*
8747 * NOTE: The {max occurs} of all the particles in the
8748 * {particles} of the group must be 0 or 1.
8749 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008750 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008751 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8752 ctxt->state,
8753 elem->name,
8754 elem->targetNamespace,
8755 1, 1, subtypes);
8756 } else if ((elem->minOccurs == 0) &&
8757 (elem->maxOccurs == 1)) {
8758
8759 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8760 ctxt->state,
8761 elem->name,
8762 elem->targetNamespace,
8763 0,
8764 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008765 subtypes);
8766 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008767 /*
8768 * NOTE: if maxOccurs == 0 then no transition will be
8769 * created.
8770 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008771 subtypes = subtypes->next;
8772 }
8773 lax = type->minOccurs == 0;
8774 ctxt->state =
8775 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8776 lax);
8777 break;
8778 }
8779 case XML_SCHEMA_TYPE_RESTRICTION:
8780 if (type->subtypes != NULL)
8781 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8782 break;
8783 case XML_SCHEMA_TYPE_EXTENSION:
8784 if (type->baseType != NULL) {
8785 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008786
8787 /*
8788 * TODO: Circular definitions will be checked at the
8789 * constraint level. So remove this when the complex type
8790 * constraints are implemented.
8791 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008792 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008793 /* TODO: Change the error code. */
8794 xmlSchemaPCustomErr(ctxt,
8795 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8796 NULL, type, type->node,
8797 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008798 return;
8799 }
8800 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008801 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008802 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008803 subtypes = type->subtypes;
8804 while (subtypes != NULL) {
8805 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8806 subtypes = subtypes->next;
8807 }
8808 } else if (type->subtypes != NULL)
8809 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8810 break;
8811 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008812 /*
8813 * Handle model group definition references.
8814 * NOTE: type->subtypes is the referenced model grop definition;
8815 * and type->subtypes->subtypes is the model group (i.e. <all> or
8816 * <choice> or <sequence>).
8817 */
8818 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8819 (type->subtypes->subtypes != NULL)) {
8820 xmlSchemaTypePtr modelGr;
8821 xmlAutomataStatePtr start, end;
8822
8823 modelGr = type->subtypes->subtypes;
8824 start = ctxt->state;
8825 end = xmlAutomataNewState(ctxt->am);
8826 if (type->maxOccurs == 1) {
8827 ctxt->state = start;
8828 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8829 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8830 } else {
8831 int counter;
8832 xmlAutomataStatePtr hop;
8833 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8834 UNBOUNDED : type->maxOccurs - 1;
8835 int minOccurs =
8836 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8837
8838 counter =
8839 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8840 hop = xmlAutomataNewState(ctxt->am);
8841 ctxt->state = start;
8842 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8843 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8844 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8845 counter);
8846 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8847 counter);
8848 }
8849 if (type->minOccurs == 0) {
8850 xmlAutomataNewEpsilon(ctxt->am, start, end);
8851 }
8852 ctxt->state = end;
8853 break;
8854 }
8855 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008856 case XML_SCHEMA_TYPE_COMPLEX:
8857 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8858 if (type->subtypes != NULL)
8859 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8860 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008861 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8862 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008863 default:
8864 xmlGenericError(xmlGenericErrorContext,
8865 "Found unexpected type %d in %s content model\n",
8866 type->type, name);
8867 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008868 }
8869}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008870
Daniel Veillard4255d502002-04-16 15:50:10 +00008871/**
8872 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008873 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00008874 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008875 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008876 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008877 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00008878 */
8879static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008880xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008881 xmlSchemaParserCtxtPtr ctxt,
8882 const xmlChar * name)
8883{
Daniel Veillard4255d502002-04-16 15:50:10 +00008884 xmlAutomataStatePtr start;
8885
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008886 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
8887 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8888 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
8889 (type->contModel != NULL))
8890 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008891
8892#ifdef DEBUG_CONTENT
8893 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008894 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008895#endif
8896
Daniel Veillard4255d502002-04-16 15:50:10 +00008897 ctxt->am = xmlNewAutomata();
8898 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008899 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008900 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008901 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008902 }
8903 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008904 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008905 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008906 type->contModel = xmlAutomataCompile(ctxt->am);
8907 if (type->contModel == NULL) {
8908 xmlSchemaPCustomErr(ctxt,
8909 XML_SCHEMAP_INTERNAL,
8910 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008911 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008912 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008913 xmlSchemaPCustomErr(ctxt,
8914 XML_SCHEMAP_NOT_DETERMINISTIC,
8915 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008916 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008917 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008918 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008919#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008920 xmlGenericError(xmlGenericErrorContext,
8921 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008922 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008923#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008924 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008925 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008926 xmlFreeAutomata(ctxt->am);
8927 ctxt->am = NULL;
8928}
8929
8930/**
8931 * xmlSchemaRefFixupCallback:
8932 * @elem: the schema element context
8933 * @ctxt: the schema parser context
8934 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008935 * Resolves the references of an element declaration
8936 * or particle, which has an element declaration as it's
8937 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008938 */
8939static void
8940xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008941 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008942 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008943 const xmlChar * context ATTRIBUTE_UNUSED,
8944 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008945{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008946 if ((ctxt == NULL) || (elem == NULL) ||
8947 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008948 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008949 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008950 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008951 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008952
Daniel Veillardc0826a72004-08-10 14:17:33 +00008953 /*
8954 * TODO: Evaluate, what errors could occur if the declaration is not
8955 * found. It might be possible that the "typefixup" might crash if
8956 * no ref declaration was found.
8957 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008958 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008959 if (elemDecl == NULL) {
8960 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008961 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008962 NULL, (xmlSchemaTypePtr) elem, elem->node,
8963 "ref", elem->ref, elem->refNs,
8964 XML_SCHEMA_TYPE_ELEMENT, NULL);
8965 } else
8966 elem->refDecl = elemDecl;
8967 } else {
8968 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8969 xmlSchemaTypePtr type;
8970
8971 /* (type definition) ... otherwise the type definition ·resolved·
8972 * to by the ·actual value· of the type [attribute] ...
8973 */
8974 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8975 elem->namedTypeNs);
8976 if (type == NULL) {
8977 xmlSchemaPResCompAttrErr(ctxt,
8978 XML_SCHEMAP_SRC_RESOLVE,
8979 NULL, (xmlSchemaTypePtr) elem, elem->node,
8980 "type", elem->namedType, elem->namedTypeNs,
8981 XML_SCHEMA_TYPE_BASIC, "type definition");
8982 } else
8983 elem->subtypes = type;
8984 }
8985 if (elem->substGroup != NULL) {
8986 xmlSchemaElementPtr substHead;
8987
8988 /*
8989 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8990 * substitutionGroup?
8991 */
8992 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008993 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008994 if (substHead == NULL) {
8995 xmlSchemaPResCompAttrErr(ctxt,
8996 XML_SCHEMAP_SRC_RESOLVE,
8997 NULL, (xmlSchemaTypePtr) elem, NULL,
8998 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8999 XML_SCHEMA_TYPE_ELEMENT, NULL);
9000 } else {
9001 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9002 /*
9003 * (type definition)...otherwise the {type definition} of the
9004 * element declaration ·resolved· to by the ·actual value· of
9005 * the substitutionGroup [attribute], if present
9006 */
9007 if (elem->subtypes == NULL)
9008 elem->subtypes = substHead->subtypes;
9009 }
9010 }
9011 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9012 (elem->substGroup == NULL))
9013 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9014 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009015}
9016
William M. Bracke7091952004-05-11 15:09:58 +00009017/**
9018 * xmlSchemaParseListRefFixup:
9019 * @type: the schema type definition
9020 * @ctxt: the schema parser context
9021 *
9022 * Fixup of the itemType reference of the list type.
9023 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009024static void
William M. Bracke7091952004-05-11 15:09:58 +00009025xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009026{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009027
Daniel Veillard01fa6152004-06-29 17:04:39 +00009028 if (((type->base == NULL) &&
9029 (type->subtypes == NULL)) ||
9030 ((type->base != NULL) &&
9031 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009032 /*
9033 * src-list-itemType-or-simpleType
9034 * Either the itemType [attribute] or the <simpleType> [child] of
9035 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009036 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009037 /*
9038 * TODO: Move this to the parse function.
9039 */
9040 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009041 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009042 NULL, type, type->node,
9043 "The attribute 'itemType' and the <simpleType> child "
9044 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009045 } else if (type->base!= NULL) {
9046 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9047 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009048 xmlSchemaPResCompAttrErr(ctxt,
9049 XML_SCHEMAP_SRC_RESOLVE,
9050 NULL, type, type->node,
9051 "itemType", type->base, type->baseNs,
9052 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009053 }
9054 }
9055 if ((type->subtypes != NULL) &&
9056 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9057 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009058}
9059
9060/**
9061 * xmlSchemaParseUnionRefCheck:
9062 * @typeDecl: the schema type definition
9063 * @ctxt: the schema parser context
9064 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009065 * Checks and builds the memberTypes of the union type.
9066 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009067 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009068static int
William M. Bracke7091952004-05-11 15:09:58 +00009069xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009070 xmlSchemaParserCtxtPtr ctxt)
9071{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009072
Daniel Veillard01fa6152004-06-29 17:04:39 +00009073 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9074 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009075
Daniel Veillard01fa6152004-06-29 17:04:39 +00009076 /* 1 If the <union> alternative is chosen, then [Definition:]
9077 * define the explicit members as the type definitions ·resolved·
9078 * to by the items in the ·actual value· of the memberTypes [attribute],
9079 * if any, followed by the type definitions corresponding to the
9080 * <simpleType>s among the [children] of <union>, if any.
9081 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009082
Daniel Veillard01fa6152004-06-29 17:04:39 +00009083 if (type->type != XML_SCHEMA_TYPE_UNION)
9084 return (-1);
9085 if (ctxt->ctxtType == NULL) {
9086 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009087 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009088 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9089 "available", NULL, NULL);
9090 return (-1);
9091 }
9092 /*
9093 * src-union-memberTypes-or-simpleTypes
9094 * Either the memberTypes [attribute] of the <union> element must
9095 * be non-empty or there must be at least one simpleType [child].
9096 */
9097 if ((type->base == NULL) &&
9098 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009099 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009100 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009101 NULL, NULL, type->node,
9102 "Either the attribute 'memberTypes' must be non-empty "
9103 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009104 }
9105
9106 ctxtType = ctxt->ctxtType;
9107 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009108 xmlAttrPtr attr;
9109 const xmlChar *cur, *end;
9110 xmlChar *tmp;
9111 const xmlChar *localName, *uri;
9112
9113 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009114 cur = type->base;
9115 do {
9116 while (IS_BLANK_CH(*cur))
9117 cur++;
9118 end = cur;
9119 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9120 end++;
9121 if (end == cur)
9122 break;
9123 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009124 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9125 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9126 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009127 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009128 xmlSchemaPResCompAttrErr(ctxt,
9129 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9130 NULL, NULL, type->node, "memberTypes", localName, uri,
9131 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009132 } else {
9133 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9134 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9135 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9136 if (link == NULL) {
9137 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9138 return (-1);
9139 }
9140 link->type = memberType;
9141 link->next = NULL;
9142 if (lastLink == NULL)
9143 ctxtType->memberTypes = link;
9144 else
9145 lastLink->next = link;
9146 lastLink = link;
9147 }
9148 xmlFree(tmp);
9149 cur = end;
9150 } while (*cur != 0);
9151 }
9152 /*
9153 * Add local simple types,
9154 */
9155 memberType = type->subtypes;
9156 while (memberType != NULL) {
9157 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9158 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9159 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9160 if (link == NULL) {
9161 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9162 return (-1);
9163 }
9164 link->type = memberType;
9165 link->next = NULL;
9166 if (lastLink == NULL)
9167 ctxtType->memberTypes = link;
9168 else
9169 lastLink->next = link;
9170 lastLink = link;
9171 memberType = memberType->next;
9172 }
9173 /*
9174 * The actual value is then formed by replacing any union type
9175 * definition in the ·explicit members· with the members of their
9176 * {member type definitions}, in order.
9177 */
9178 link = ctxtType->memberTypes;
9179 while (link != NULL) {
9180 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9181 subLink = link->type->memberTypes;
9182 if (subLink != NULL) {
9183 link->type = subLink->type;
9184 if (subLink->next != NULL) {
9185 lastLink = link->next;
9186 subLink = subLink->next;
9187 prevLink = link;
9188 while (subLink != NULL) {
9189 newLink = (xmlSchemaTypeLinkPtr)
9190 xmlMalloc(sizeof(xmlSchemaTypeLink));
9191 if (newLink == NULL) {
9192 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9193 NULL);
9194 return (-1);
9195 }
9196 newLink->type = memberType;
9197 prevLink->next = newLink;
9198 prevLink = newLink;
9199 newLink->next = lastLink;
9200
9201 subLink = subLink->next;
9202 }
9203 }
9204 }
9205 }
9206 link = link->next;
9207 }
9208
9209 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009210}
9211
Daniel Veillard4255d502002-04-16 15:50:10 +00009212/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009213 * xmlSchemaIsDerivedFromBuiltInType:
9214 * @ctxt: the schema parser context
9215 * @type: the type definition
9216 * @valType: the value type
9217 *
9218 *
9219 * Returns 1 if the type has the given value type, or
9220 * is derived from such a type.
9221 */
William M. Brack803812b2004-06-03 02:11:24 +00009222static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009223xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9224 xmlSchemaTypePtr type, int valType)
9225{
9226 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009227 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009228 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009229 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009230 return(1);
9231 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9232 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9233 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9234 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9235 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9236 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9237 if (type->baseType != NULL)
9238 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9239 valType));
9240 } else if ((type->subtypes != NULL) &&
9241 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9242 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9243 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9244 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9245 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9246 valType));
9247 }
9248
9249 return (0);
9250}
9251
9252/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009253 * xmlSchemaIsDerivedFromBuiltInType:
9254 * @type: the simpleType definition
9255 *
9256 * Returns the primitive type of the given type or
9257 * NULL in case of error.
9258 */
9259static xmlSchemaTypePtr
9260xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9261{
9262 while (type != NULL) {
9263 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9264 return (type);
9265 type = type->baseType;
9266 }
9267
9268 return (NULL);
9269}
9270
9271
9272/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009273 * xmlSchemaBuildAttributeUsesOwned:
9274 * @ctxt: the schema parser context
9275 * @type: the complex type definition
9276 * @cur: the attribute declaration list
9277 * @lastUse: the top of the attribute use list
9278 *
9279 * Builds the attribute uses list on the given complex type.
9280 * This one is supposed to be called by
9281 * xmlSchemaBuildAttributeValidation only.
9282 */
9283static int
9284xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9285 xmlSchemaAttributePtr cur,
9286 xmlSchemaAttributeLinkPtr *uses,
9287 xmlSchemaAttributeLinkPtr *lastUse)
9288{
9289 xmlSchemaAttributeLinkPtr tmp;
9290 while (cur != NULL) {
9291 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9292 /*
9293 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9294 * to by the ·actual value·s of the ref [attribute] of the
9295 * <attributeGroup> [children], if any."
9296 */
9297 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9298 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9299 lastUse) == -1) {
9300 return (-1);
9301 }
9302 } else {
9303 /* W3C: "1 The set of attribute uses corresponding to the
9304 * <attribute> [children], if any."
9305 */
9306 tmp = (xmlSchemaAttributeLinkPtr)
9307 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9308 if (tmp == NULL) {
9309 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9310 return (-1);
9311 }
9312 tmp->attr = cur;
9313 tmp->next = NULL;
9314 if (*uses == NULL)
9315 *uses = tmp;
9316 else
9317 (*lastUse)->next = tmp;
9318 *lastUse = tmp;
9319 }
9320 cur = cur->next;
9321 }
9322 return (0);
9323}
9324
Daniel Veillard50355f02004-06-08 17:52:16 +00009325/**
9326 * xmlSchemaCloneWildcardNsConstraints:
9327 * @ctxt: the schema parser context
9328 * @dest: the destination wildcard
9329 * @source: the source wildcard
9330 *
9331 * Clones the namespace constraints of source
9332 * and assignes them to dest.
9333 * Returns -1 on internal error, 0 otherwise.
9334 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009335static int
9336xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9337 xmlSchemaWildcardPtr *dest,
9338 xmlSchemaWildcardPtr source)
9339{
9340 xmlSchemaWildcardNsPtr cur, tmp, last;
9341
9342 if ((source == NULL) || (*dest == NULL))
9343 return(-1);
9344 (*dest)->any = source->any;
9345 cur = source->nsSet;
9346 last = NULL;
9347 while (cur != NULL) {
9348 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9349 if (tmp == NULL)
9350 return(-1);
9351 tmp->value = cur->value;
9352 if (last == NULL)
9353 (*dest)->nsSet = tmp;
9354 else
9355 last->next = tmp;
9356 last = tmp;
9357 cur = cur->next;
9358 }
9359 if ((*dest)->negNsSet != NULL)
9360 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9361 if (source->negNsSet != NULL) {
9362 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9363 if ((*dest)->negNsSet == NULL)
9364 return(-1);
9365 (*dest)->negNsSet->value = source->negNsSet->value;
9366 } else
9367 (*dest)->negNsSet = NULL;
9368 return(0);
9369}
9370
Daniel Veillard50355f02004-06-08 17:52:16 +00009371/**
9372 * xmlSchemaUnionWildcards:
9373 * @ctxt: the schema parser context
9374 * @completeWild: the first wildcard
9375 * @curWild: the second wildcard
9376 *
9377 * Unions the namespace constraints of the given wildcards.
9378 * @completeWild will hold the resulting union.
9379 * Returns a positive error code on failure, -1 in case of an
9380 * internal error, 0 otherwise.
9381 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009382static int
9383xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9384 xmlSchemaWildcardPtr completeWild,
9385 xmlSchemaWildcardPtr curWild)
9386{
9387 xmlSchemaWildcardNsPtr cur, curB, tmp;
9388
9389 /*
9390 * 1 If O1 and O2 are the same value, then that value must be the
9391 * value.
9392 */
9393 if ((completeWild->any == curWild->any) &&
9394 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9395 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9396
9397 if ((completeWild->negNsSet == NULL) ||
9398 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9399
9400 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009401 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009402
9403 /*
9404 * Check equality of sets.
9405 */
9406 cur = completeWild->nsSet;
9407 while (cur != NULL) {
9408 found = 0;
9409 curB = curWild->nsSet;
9410 while (curB != NULL) {
9411 if (cur->value == curB->value) {
9412 found = 1;
9413 break;
9414 }
9415 curB = curB->next;
9416 }
9417 if (!found)
9418 break;
9419 cur = cur->next;
9420 }
9421 if (found)
9422 return(0);
9423 } else
9424 return(0);
9425 }
9426 }
9427 /*
9428 * 2 If either O1 or O2 is any, then any must be the value
9429 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009430 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009431 if (completeWild->any == 0) {
9432 completeWild->any = 1;
9433 if (completeWild->nsSet != NULL) {
9434 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9435 completeWild->nsSet = NULL;
9436 }
9437 if (completeWild->negNsSet != NULL) {
9438 xmlFree(completeWild->negNsSet);
9439 completeWild->negNsSet = NULL;
9440 }
9441 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009442 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009443 }
9444 /*
9445 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9446 * then the union of those sets must be the value.
9447 */
9448 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9449 int found;
9450 xmlSchemaWildcardNsPtr start;
9451
9452 cur = curWild->nsSet;
9453 start = completeWild->nsSet;
9454 while (cur != NULL) {
9455 found = 0;
9456 curB = start;
9457 while (curB != NULL) {
9458 if (cur->value == curB->value) {
9459 found = 1;
9460 break;
9461 }
9462 curB = curB->next;
9463 }
9464 if (!found) {
9465 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9466 if (tmp == NULL)
9467 return (-1);
9468 tmp->value = cur->value;
9469 tmp->next = completeWild->nsSet;
9470 completeWild->nsSet = tmp;
9471 }
9472 cur = cur->next;
9473 }
9474
9475 return(0);
9476 }
9477 /*
9478 * 4 If the two are negations of different values (namespace names
9479 * or ·absent·), then a pair of not and ·absent· must be the value.
9480 */
9481 if ((completeWild->negNsSet != NULL) &&
9482 (curWild->negNsSet != NULL) &&
9483 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9484 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009485
9486 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009487 }
9488 /*
9489 * 5.
9490 */
9491 if (((completeWild->negNsSet != NULL) &&
9492 (completeWild->negNsSet->value != NULL) &&
9493 (curWild->nsSet != NULL)) ||
9494 ((curWild->negNsSet != NULL) &&
9495 (curWild->negNsSet->value != NULL) &&
9496 (completeWild->nsSet != NULL))) {
9497
9498 int nsFound, absentFound = 0;
9499
9500 if (completeWild->nsSet != NULL) {
9501 cur = completeWild->nsSet;
9502 curB = curWild->negNsSet;
9503 } else {
9504 cur = curWild->nsSet;
9505 curB = completeWild->negNsSet;
9506 }
9507 nsFound = 0;
9508 while (cur != NULL) {
9509 if (cur->value == NULL)
9510 absentFound = 1;
9511 else if (cur->value == curB->value)
9512 nsFound = 1;
9513 if (nsFound && absentFound)
9514 break;
9515 cur = cur->next;
9516 }
9517
9518 if (nsFound && absentFound) {
9519 /*
9520 * 5.1 If the set S includes both the negated namespace
9521 * name and ·absent·, then any must be the value.
9522 */
9523 completeWild->any = 1;
9524 if (completeWild->nsSet != NULL) {
9525 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9526 completeWild->nsSet = NULL;
9527 }
9528 if (completeWild->negNsSet != NULL) {
9529 xmlFree(completeWild->negNsSet);
9530 completeWild->negNsSet = NULL;
9531 }
9532 } else if (nsFound && (!absentFound)) {
9533 /*
9534 * 5.2 If the set S includes the negated namespace name
9535 * but not ·absent·, then a pair of not and ·absent· must
9536 * be the value.
9537 */
9538 if (completeWild->nsSet != NULL) {
9539 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9540 completeWild->nsSet = NULL;
9541 }
9542 if (completeWild->negNsSet == NULL) {
9543 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9544 if (completeWild->negNsSet == NULL)
9545 return (-1);
9546 }
9547 completeWild->negNsSet->value = NULL;
9548 } else if ((!nsFound) && absentFound) {
9549 /*
9550 * 5.3 If the set S includes ·absent· but not the negated
9551 * namespace name, then the union is not expressible.
9552 */
9553 xmlSchemaPErr(ctxt, completeWild->node,
9554 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009555 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009556 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009557 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009558 } else if ((!nsFound) && (!absentFound)) {
9559 /*
9560 * 5.4 If the set S does not include either the negated namespace
9561 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9562 * and a namespace name must be the value.
9563 */
9564 if (completeWild->negNsSet == NULL) {
9565 if (completeWild->nsSet != NULL) {
9566 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9567 completeWild->nsSet = NULL;
9568 }
9569 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9570 if (completeWild->negNsSet == NULL)
9571 return (-1);
9572 completeWild->negNsSet->value = curWild->negNsSet->value;
9573 }
9574 }
9575 return (0);
9576 }
9577 /*
9578 * 6.
9579 */
9580 if (((completeWild->negNsSet != NULL) &&
9581 (completeWild->negNsSet->value == NULL) &&
9582 (curWild->nsSet != NULL)) ||
9583 ((curWild->negNsSet != NULL) &&
9584 (curWild->negNsSet->value == NULL) &&
9585 (completeWild->nsSet != NULL))) {
9586
9587 if (completeWild->nsSet != NULL) {
9588 cur = completeWild->nsSet;
9589 } else {
9590 cur = curWild->nsSet;
9591 }
9592 while (cur != NULL) {
9593 if (cur->value == NULL) {
9594 /*
9595 * 6.1 If the set S includes ·absent·, then any must be the
9596 * value.
9597 */
9598 completeWild->any = 1;
9599 if (completeWild->nsSet != NULL) {
9600 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9601 completeWild->nsSet = NULL;
9602 }
9603 if (completeWild->negNsSet != NULL) {
9604 xmlFree(completeWild->negNsSet);
9605 completeWild->negNsSet = NULL;
9606 }
9607 return (0);
9608 }
9609 cur = cur->next;
9610 }
9611 if (completeWild->negNsSet == NULL) {
9612 /*
9613 * 6.2 If the set S does not include ·absent·, then a pair of not
9614 * and ·absent· must be the value.
9615 */
9616 if (completeWild->nsSet != NULL) {
9617 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9618 completeWild->nsSet = NULL;
9619 }
9620 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9621 if (completeWild->negNsSet == NULL)
9622 return (-1);
9623 completeWild->negNsSet->value = NULL;
9624 }
9625 return (0);
9626 }
9627 return (0);
9628
9629}
9630
Daniel Veillard50355f02004-06-08 17:52:16 +00009631/**
9632 * xmlSchemaIntersectWildcards:
9633 * @ctxt: the schema parser context
9634 * @completeWild: the first wildcard
9635 * @curWild: the second wildcard
9636 *
9637 * Intersects the namespace constraints of the given wildcards.
9638 * @completeWild will hold the resulting intersection.
9639 * Returns a positive error code on failure, -1 in case of an
9640 * internal error, 0 otherwise.
9641 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009642static int
9643xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9644 xmlSchemaWildcardPtr completeWild,
9645 xmlSchemaWildcardPtr curWild)
9646{
William M. Brack803812b2004-06-03 02:11:24 +00009647 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009648
9649 /*
9650 * 1 If O1 and O2 are the same value, then that value must be the
9651 * value.
9652 */
9653 if ((completeWild->any == curWild->any) &&
9654 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9655 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9656
9657 if ((completeWild->negNsSet == NULL) ||
9658 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9659
9660 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009661 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009662
9663 /*
9664 * Check equality of sets.
9665 */
9666 cur = completeWild->nsSet;
9667 while (cur != NULL) {
9668 found = 0;
9669 curB = curWild->nsSet;
9670 while (curB != NULL) {
9671 if (cur->value == curB->value) {
9672 found = 1;
9673 break;
9674 }
9675 curB = curB->next;
9676 }
9677 if (!found)
9678 break;
9679 cur = cur->next;
9680 }
9681 if (found)
9682 return(0);
9683 } else
9684 return(0);
9685 }
9686 }
9687 /*
9688 * 2 If either O1 or O2 is any, then the other must be the value.
9689 */
9690 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9691 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9692 return(-1);
9693 return(0);
9694 }
9695 /*
9696 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9697 * name or ·absent·) and the other is a set of (namespace names or
9698 * ·absent·), then that set, minus the negated value if it was in
9699 * the set, minus ·absent· if it was in the set, must be the value.
9700 */
9701 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9702 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9703 const xmlChar *neg;
9704
9705 if (completeWild->nsSet == NULL) {
9706 neg = completeWild->negNsSet->value;
9707 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9708 return(-1);
9709 } else
9710 neg = curWild->negNsSet->value;
9711 /*
9712 * Remove absent and negated.
9713 */
9714 prev = NULL;
9715 cur = completeWild->nsSet;
9716 while (cur != NULL) {
9717 if (cur->value == NULL) {
9718 if (prev == NULL)
9719 completeWild->nsSet = cur->next;
9720 else
9721 prev->next = cur->next;
9722 xmlFree(cur);
9723 break;
9724 }
9725 prev = cur;
9726 cur = cur->next;
9727 }
9728 if (neg != NULL) {
9729 prev = NULL;
9730 cur = completeWild->nsSet;
9731 while (cur != NULL) {
9732 if (cur->value == neg) {
9733 if (prev == NULL)
9734 completeWild->nsSet = cur->next;
9735 else
9736 prev->next = cur->next;
9737 xmlFree(cur);
9738 break;
9739 }
9740 prev = cur;
9741 cur = cur->next;
9742 }
9743 }
9744
9745 return(0);
9746 }
9747 /*
9748 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9749 * then the intersection of those sets must be the value.
9750 */
9751 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9752 int found;
9753
9754 cur = completeWild->nsSet;
9755 prev = NULL;
9756 while (cur != NULL) {
9757 found = 0;
9758 curB = curWild->nsSet;
9759 while (curB != NULL) {
9760 if (cur->value == curB->value) {
9761 found = 1;
9762 break;
9763 }
9764 curB = curB->next;
9765 }
9766 if (!found) {
9767 if (prev == NULL)
9768 completeWild->nsSet = cur->next;
9769 else
9770 prev->next = cur->next;
9771 tmp = cur->next;
9772 xmlFree(cur);
9773 cur = tmp;
9774 continue;
9775 }
9776 prev = cur;
9777 cur = cur->next;
9778 }
9779
9780 return(0);
9781 }
9782 /* 5 If the two are negations of different namespace names,
9783 * then the intersection is not expressible
9784 */
9785 if ((completeWild->negNsSet != NULL) &&
9786 (curWild->negNsSet != NULL) &&
9787 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9788 (completeWild->negNsSet->value != NULL) &&
9789 (curWild->negNsSet->value != NULL)) {
9790
9791 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009792 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009793 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009794 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009795 }
9796 /*
9797 * 6 If the one is a negation of a namespace name and the other
9798 * is a negation of ·absent·, then the one which is the negation
9799 * of a namespace name must be the value.
9800 */
9801 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9802 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9803 (completeWild->negNsSet->value == NULL)) {
9804 completeWild->negNsSet->value = curWild->negNsSet->value;
9805 }
9806 return(0);
9807}
9808
Daniel Veillard50355f02004-06-08 17:52:16 +00009809/**
9810 * xmlSchemaIsWildcardNsConstraintSubset:
9811 * @ctxt: the schema parser context
9812 * @wildA: the first wildcard
9813 * @wildB: the second wildcard
9814 *
9815 * Returns 1 if the namespace constraint of @wildA is an intensional
9816 * subset of @wildB, 0 otherwise.
9817 */
9818static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009819xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9820 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009821{
Daniel Veillard3646d642004-06-02 19:19:14 +00009822
Daniel Veillard50355f02004-06-08 17:52:16 +00009823 /*
9824 * Schema Component Constraint: Wildcard Subset
9825 */
9826 /*
9827 * 1 super must be any.
9828 */
9829 if (wildB->any)
9830 return (1);
9831 /*
9832 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9833 * 2.2 super must be a pair of not and the same value.
9834 */
9835 if ((wildA->negNsSet != NULL) &&
9836 (wildB->negNsSet != NULL) &&
9837 (wildA->negNsSet->value == wildA->negNsSet->value))
9838 return (1);
9839 /*
9840 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9841 */
9842 if (wildA->nsSet != NULL) {
9843 /*
9844 * 3.2.1 super must be the same set or a superset thereof.
9845 */
9846 if (wildB->nsSet != NULL) {
9847 xmlSchemaWildcardNsPtr cur, curB;
9848 int found = 0;
9849
9850 cur = wildA->nsSet;
9851 while (cur != NULL) {
9852 found = 0;
9853 curB = wildB->nsSet;
9854 while (curB != NULL) {
9855 if (cur->value == curB->value) {
9856 found = 1;
9857 break;
9858 }
9859 curB = curB->next;
9860 }
9861 if (!found)
9862 return (0);
9863 cur = cur->next;
9864 }
9865 if (found)
9866 return (1);
9867 } else if (wildB->negNsSet != NULL) {
9868 xmlSchemaWildcardNsPtr cur;
9869 /*
9870 * 3.2.2 super must be a pair of not and a namespace name or
9871 * ·absent· and that value must not be in sub's set.
9872 */
9873 cur = wildA->nsSet;
9874 while (cur != NULL) {
9875 if (cur->value == wildB->negNsSet->value)
9876 return (0);
9877 cur = cur->next;
9878 }
9879 return (1);
9880 }
9881 }
9882 return (0);
9883}
9884
9885/**
9886 * xmlSchemaBuildCompleteAttributeWildcard:
9887 * @ctxt: the schema parser context
9888 * @attrs: the attribute list
9889 * @completeWild: the resulting complete wildcard
9890 *
9891 * Returns -1 in case of an internal error, 0 otherwise.
9892 */
9893static int
9894xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9895 xmlSchemaAttributePtr attrs,
9896 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009897{
9898 while (attrs != NULL) {
9899 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9900 xmlSchemaAttributeGroupPtr group;
9901
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009902 group = (xmlSchemaAttributeGroupPtr) attrs;
9903 /*
9904 * Handle attribute group references.
9905 */
9906 if (group->ref != NULL) {
9907 if (group->refItem == NULL) {
9908 /*
9909 * TODO: Should we raise a warning here?
9910 */
9911 /*
9912 * The referenced attribute group definition could not
9913 * be resolved beforehand, so skip.
9914 */
9915 attrs = attrs->next;
9916 continue;
9917 } else
9918 group = group->refItem;
9919 }
9920 /*
9921 * For every attribute group definition, an intersected wildcard
9922 * will be created (assumed that a wildcard exists on the
9923 * particular attr. gr. def. or on any contained attr. gr. def
9924 * at all).
9925 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
9926 * that the intersection will be performed only once.
9927 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009928 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9929 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009930 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9931 group->attributes, &group->attributeWildcard) == -1)
9932 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009933 }
9934 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9935 }
9936 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009937 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009938 /*
9939 * Copy the first encountered wildcard as context, except for the annotation.
9940 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009941 *completeWild = xmlSchemaAddWildcard(ctxt);
9942 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9943 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9944 completeWild, group->attributeWildcard) == -1)
9945 return (-1);
9946 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009947 /*
9948 * Although the complete wildcard might not correspond to any
9949 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009950 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +00009951 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009952 (*completeWild)->node = group->attributeWildcard->node;
9953
9954 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9955 xmlSchemaFreeWildcard(*completeWild);
9956 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009957 }
9958 }
9959 }
9960 attrs = attrs->next;
9961 }
9962
Daniel Veillard50355f02004-06-08 17:52:16 +00009963 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009964}
9965
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009966static int
9967xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
9968 int *fixed,
9969 const xmlChar **value,
9970 xmlSchemaValPtr *val)
9971{
9972 *fixed = 0;
9973 *value = NULL;
9974 if (val != 0)
9975 *val = NULL;
9976
9977 if (item->defValue == NULL)
9978 item = item->refDecl;
9979
9980 if (item == NULL)
9981 return (0);
9982
9983 if (item->defValue != NULL) {
9984 *value = item->defValue;
9985 if (val != 0)
9986 *val = item->defVal;
9987 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
9988 *fixed = 1;
9989 return (1);
9990 }
9991 return (0);
9992}
Daniel Veillard3646d642004-06-02 19:19:14 +00009993/**
9994 * xmlSchemaMatchesWildcardNs:
9995 * @wild: the wildcard
9996 * @ns: the namespace
9997 *
9998 *
9999 * Returns 1 if the given namespace matches the wildcard,
10000 * 0 otherwise.
10001 */
10002static int
10003xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10004{
10005 if (wild == NULL)
10006 return(0);
10007
10008 if (wild->any)
10009 return(1);
10010 else if (wild->nsSet != NULL) {
10011 xmlSchemaWildcardNsPtr cur;
10012
10013 cur = wild->nsSet;
10014 while (cur != NULL) {
10015 if (xmlStrEqual(cur->value, ns))
10016 return(1);
10017 cur = cur->next;
10018 }
10019 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10020 (!xmlStrEqual(wild->negNsSet->value, ns)))
10021 return(1);
10022
10023 return(0);
10024}
10025
10026/**
10027 * xmlSchemaBuildAttributeValidation:
10028 * @ctxt: the schema parser context
10029 * @type: the complex type definition
10030 *
10031 *
10032 * Builds the wildcard and the attribute uses on the given complex type.
10033 * Returns -1 if an internal error occurs, 0 otherwise.
10034 */
10035static int
10036xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10037{
10038 xmlSchemaTypePtr baseType = NULL;
10039 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010040 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010041 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010042 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010043 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010044 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010045 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010046
Daniel Veillard01fa6152004-06-29 17:04:39 +000010047 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010048 /*
10049 * Complex Type Definition with complex content Schema Component.
10050 *
10051 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010052 * TODO: Add checks for absent referenced attribute declarations and
10053 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010054 */
10055 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010056 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010057 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010058 "attribute uses already builded.\n",
10059 NULL, NULL);
10060 return (-1);
10061 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010062 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010063 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010064 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010065 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010066 type->name, NULL);
10067 return (-1);
10068 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010069 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010070 if (baseType == anyType)
10071 baseIsAnyType = 1;
10072 /*
10073 * Inherit the attribute uses of the base type.
10074 */
10075 /*
10076 * NOTE: It is allowed to "extend" the anyType complex type.
10077 */
10078 if (!baseIsAnyType) {
10079 if (baseType != NULL) {
10080 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10081 tmp = (xmlSchemaAttributeLinkPtr)
10082 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10083 if (tmp == NULL) {
10084 xmlSchemaPErrMemory(ctxt,
10085 "building attribute uses of complexType", NULL);
10086 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010087 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010088 tmp->attr = cur->attr;
10089 tmp->next = NULL;
10090 if (type->attributeUses == NULL) {
10091 type->attributeUses = tmp;
10092 } else
10093 lastBaseUse->next = tmp;
10094 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010095 }
10096 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010097 }
10098 if ((type->subtypes != NULL) &&
10099 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10100 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010101 /*
10102 * type --> (<simpleContent>|<complexContent>)
10103 * --> (<restriction>|<extension>) --> attributes
10104 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010105 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010106 } else {
10107 /* Short hand form of the complexType. */
10108 attrs = type->attributes;
10109 }
10110 /*
10111 * Handle attribute wildcards.
10112 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010113 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10114 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010115 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010116 * NOTE: During the parse time, the wildcard is created on the complexType
10117 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010118 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010119 if (err == -1) {
10120 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10121 "Internal error: xmlSchemaBuildAttributeValidation: "
10122 "failed to build an intersected attribute wildcard.\n",
10123 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010124 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010125 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010126
10127 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10128 ((baseIsAnyType) ||
10129 ((baseType != NULL) &&
10130 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10131 (baseType->attributeWildcard != NULL)))) {
10132 if (type->attributeWildcard != NULL) {
10133 /*
10134 * Union the complete wildcard with the base wildcard.
10135 */
10136 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10137 baseType->attributeWildcard) == -1)
10138 return (-1);
10139 } else {
10140 /*
10141 * Just inherit the wildcard.
10142 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010143 /*
10144 * NOTE: This is the only case where an attribute
10145 * wildcard is shared.
10146 */
10147 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10148 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010149 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010150 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010151 }
10152
10153 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10154 if (type->attributeWildcard != NULL) {
10155 /*
10156 * Derivation Valid (Restriction, Complex)
10157 * 4.1 The {base type definition} must also have one.
10158 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010159 if (baseType->attributeWildcard == NULL) {
10160 xmlSchemaPCustomErr(ctxt,
10161 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10162 NULL, type, NULL,
10163 "The type has an attribute wildcard, "
10164 "but the base type %s does not have one",
10165 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10166 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010167 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010168 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010169 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10170 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010171 xmlSchemaPCustomErr(ctxt,
10172 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10173 NULL, type, NULL,
10174 "The attribute wildcard is not a valid "
10175 "subset of the wildcard in the base type %s",
10176 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10177 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010178 return (1);
10179 }
10180 /* 4.3 Unless the {base type definition} is the ·ur-type
10181 * definition·, the complex type definition's {attribute
10182 * wildcard}'s {process contents} must be identical to or
10183 * stronger than the {base type definition}'s {attribute
10184 * wildcard}'s {process contents}, where strict is stronger
10185 * than lax is stronger than skip.
10186 */
10187 if ((type->baseType != anyType) &&
10188 (type->attributeWildcard->processContents <
10189 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010190 xmlSchemaPCustomErr(ctxt,
10191 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10192 NULL, type, NULL,
10193 "The 'process contents' of the attribute wildcard is weaker than "
10194 "the one in the base type %s",
10195 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10196 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010197 return (1);
10198 }
10199 }
10200 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10201 /*
10202 * Derivation Valid (Extension)
10203 * At this point the type and the base have both, either
10204 * no wildcard or a wildcard.
10205 */
10206 if ((baseType->attributeWildcard != NULL) &&
10207 (baseType->attributeWildcard != type->attributeWildcard)) {
10208 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010209 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010210 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010211 xmlSchemaPCustomErr(ctxt,
10212 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10213 NULL, type, NULL,
10214 "The attribute wildcard is not a valid "
10215 "superset of the one in the base type %s",
10216 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10217 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010218 return (1);
10219 }
10220 }
10221 }
10222
Daniel Veillard3646d642004-06-02 19:19:14 +000010223 /*
10224 * Gather attribute uses defined by this type.
10225 */
10226 if (attrs != NULL) {
10227 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10228 &uses, &lastUse) == -1) {
10229 return (-1);
10230 }
10231 }
10232 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10233 * "Two distinct attribute declarations in the {attribute uses} must
10234 * not have identical {name}s and {target namespace}s."
10235 *
10236 * For "extension" this is done further down.
10237 */
10238 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10239 cur = uses;
10240 while (cur != NULL) {
10241 tmp = cur->next;
10242 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010243 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10244 xmlSchemaGetAttrName(tmp->attr))) &&
10245 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10246 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10247
10248 xmlSchemaPAttrUseErr(ctxt,
10249 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10250 NULL, type, NULL, cur->attr,
10251 "Duplicate attribute use %s specified",
10252 xmlSchemaFormatNsUriLocal(&str,
10253 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10254 xmlSchemaGetAttrName(tmp->attr))
10255 );
10256 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010257 break;
10258 }
10259 tmp = tmp->next;
10260 }
10261 cur = cur->next;
10262 }
10263 }
10264 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10265 /*
10266 * Derive by restriction.
10267 */
10268 if (baseIsAnyType) {
10269 type->attributeUses = uses;
10270 } else {
10271 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010272 const xmlChar *bEffValue;
10273 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010274
10275 cur = uses;
10276 while (cur != NULL) {
10277 found = 0;
10278 base = type->attributeUses;
10279 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010280 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10281 xmlSchemaGetAttrName(base->attr)) &&
10282 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10283 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010284
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010285 found = 1;
10286
Daniel Veillard3646d642004-06-02 19:19:14 +000010287 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10288 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10289 /*
10290 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010291 */
10292 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010293 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010294 NULL, type, NULL, cur->attr,
10295 "The 'optional' use is inconsistent with a matching "
10296 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010297 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10298 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10299 /*
10300 * derivation-ok-restriction 3
10301 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010302 xmlSchemaPCustomErr(ctxt,
10303 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10304 NULL, type, NULL,
10305 "A matching attribute use for the 'required' "
10306 "attribute use %s of the base type is missing",
10307 xmlSchemaFormatNsUriLocal(&str,
10308 xmlSchemaGetAttrTargetNsURI(base->attr),
10309 xmlSchemaGetAttrName(base->attr)));
10310 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010311 } else {
10312 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010313 * 2.1.3 [Definition:] Let the effective value
10314 * constraint of an attribute use be its {value
10315 * constraint}, if present, otherwise its {attribute
10316 * declaration}'s {value constraint} .
10317 */
10318 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10319 &bEffValue, 0);
10320 /*
10321 * 2.1.3 ... one of the following must be true
10322 *
10323 * 2.1.3.1 B's ·effective value constraint· is
10324 * ·absent· or default.
10325 */
10326 if ((bEffValue != NULL) &&
10327 (effFixed == 1)) {
10328 const xmlChar *rEffValue = NULL;
10329
10330 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10331 &rEffValue, 0);
10332 /*
10333 * 2.1.3.2 R's ·effective value constraint· is
10334 * fixed with the same string as B's.
10335 */
10336 if ((effFixed == 0) ||
10337 (! xmlStrEqual(rEffValue, bEffValue))) {
10338 xmlSchemaPAttrUseErr(ctxt,
10339 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10340 NULL, type, NULL, cur->attr,
10341 "The effective value constraint of the "
10342 "attribute use is inconsistent with "
10343 "its correspondent of the base type",
10344 NULL);
10345 }
10346 }
10347 /*
10348 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10349 */
10350 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010351 * Override the attribute use.
10352 */
10353 base->attr = cur->attr;
10354 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010355
Daniel Veillard3646d642004-06-02 19:19:14 +000010356 break;
10357 }
10358 base = base->next;
10359 }
10360
10361 if (!found) {
10362 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10363 /*
10364 * derivation-ok-restriction 2.2
10365 */
10366 if ((type->attributeWildcard != NULL) &&
10367 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10368 cur->attr->targetNamespace))
10369 found = 1;
10370
10371 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010372 xmlSchemaPAttrUseErr(ctxt,
10373 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10374 NULL, type, NULL, cur->attr,
10375 "Neither a matching attribute use, "
10376 "nor a matching wildcard in the base type does exist",
10377 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010378 } else {
10379 /*
10380 * Add the attribute use.
10381 *
10382 * Note that this may lead to funny derivation error reports, if
10383 * multiple equal attribute uses exist; but this is not
10384 * allowed anyway, and it will be reported beforehand.
10385 */
10386 tmp = cur;
10387 if (prev != NULL)
10388 prev->next = cur->next;
10389 else
10390 uses = cur->next;
10391 cur = cur->next;
10392 if (type->attributeUses == NULL) {
10393 type->attributeUses = tmp;
10394 } else
10395 lastBaseUse->next = tmp;
10396 lastBaseUse = tmp;
10397
10398 continue;
10399 }
10400 }
10401 }
10402 prev = cur;
10403 cur = cur->next;
10404 }
10405 if (uses != NULL)
10406 xmlSchemaFreeAttributeUseList(uses);
10407 }
10408 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10409 /*
10410 * The spec allows only appending, and not other kinds of extensions.
10411 *
10412 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10413 */
10414 if (uses != NULL) {
10415 if (type->attributeUses == NULL) {
10416 type->attributeUses = uses;
10417 } else
10418 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010419 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010420 } else {
10421 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010422 * Derive implicitely from the ur-type.
10423 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010424 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010425 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010426 /*
10427 * 3.4.6 -> Complex Type Definition Properties Correct
10428 */
10429 if (type->attributeUses != NULL) {
10430 cur = type->attributeUses;
10431 prev = NULL;
10432 while (cur != NULL) {
10433 /*
10434 * 4. Two distinct attribute declarations in the {attribute uses} must
10435 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010436 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010437 * Note that this was already done for "restriction" and types derived from
10438 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010439 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010440 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10441 tmp = cur->next;
10442 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010443 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10444 xmlSchemaGetAttrName(tmp->attr))) &&
10445 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10446 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010447
Daniel Veillardc0826a72004-08-10 14:17:33 +000010448 xmlSchemaPAttrUseErr(ctxt,
10449 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10450 NULL, type, NULL, tmp->attr,
10451 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010452 break;
10453 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010454 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010455 }
10456 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010457 /*
10458 * 5. Two distinct attribute declarations in the {attribute uses} must
10459 * not have {type definition}s which are or are derived from ID.
10460 */
10461 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010462 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010463 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010464 xmlSchemaPAttrUseErr(ctxt,
10465 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10466 NULL, type, NULL, cur->attr,
10467 "There must not exist more than one attribute use, "
10468 "declared of type 'ID' or derived from it",
10469 NULL);
10470 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010471 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010472 id = cur;
10473 }
10474 /*
10475 * Remove "prohibited" attribute uses. The reason this is done at this late
10476 * stage is to be able to catch dublicate attribute uses. So we had to keep
10477 * prohibited uses in the list as well.
10478 */
10479 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10480 tmp = cur;
10481 if (prev == NULL)
10482 type->attributeUses = cur->next;
10483 else
10484 prev->next = cur->next;
10485 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010486 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010487 } else {
10488 prev = cur;
10489 cur = cur->next;
10490 }
10491 }
10492 }
10493 /*
10494 * TODO: This check should be removed if we are 100% sure of
10495 * the base type attribute uses already being built.
10496 */
10497 if ((baseType != NULL) && (!baseIsAnyType) &&
10498 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10499 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010500 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010501 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010502 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010503 baseType->name, NULL);
10504 }
10505 return (0);
10506}
10507
10508/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010509 * xmlSchemaTypeFinalContains:
10510 * @schema: the schema
10511 * @type: the type definition
10512 * @final: the final
10513 *
10514 * Evaluates if a type definition contains the given "final".
10515 * This does take "finalDefault" into account as well.
10516 *
10517 * Returns 1 if the type does containt the given "final",
10518 * 0 otherwise.
10519 */
10520static int
10521xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10522{
10523 int tfinal = final, tflags = type->flags;
10524
10525 if (type == NULL)
10526 return (0);
10527 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10528 switch (final) {
10529 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10530 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10531 break;
10532 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10533 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10534 break;
10535 case XML_SCHEMAS_TYPE_FINAL_LIST:
10536 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10537 break;
10538 case XML_SCHEMAS_TYPE_FINAL_UNION:
10539 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10540 break;
10541 }
10542 tflags = schema->flags;
10543 }
10544 if (tflags & tfinal)
10545 return (1);
10546 else
10547 return (0);
10548
10549}
10550
10551/**
10552 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10553 * @type: the Union Simple Type
10554 *
10555 * Returns a list of member types of @type if existing,
10556 * returns NULL otherwise.
10557 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010558static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010559xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10560{
10561 while (type != NULL) {
10562 if (type->memberTypes != NULL)
10563 return (type->memberTypes);
10564 else
10565 type = type->baseType;
10566 }
10567 return (NULL);
10568}
10569
10570/**
10571 * xmlSchemaGetListSimpleTypeItemType:
10572 * @type: the simple type definition
10573 *
10574 * Returns the item type definition of the list simple type.
10575 */
10576static xmlSchemaTypePtr
10577xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10578{
10579 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10580 return (NULL);
10581 /*
10582 * Note: In libxml2, the built-in types do not reflect
10583 * the datatype hierarchy (yet?) - we have to treat them
10584 * in a special way.
10585 */
10586 if (type->type == XML_SCHEMA_TYPE_BASIC)
10587 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10588 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10589 /* 1 If the <list> alternative is chosen, then the type
10590 * definition ·resolved· to by the ·actual value· of the
10591 * itemType [attribute] of <list>, if present, otherwise
10592 * the type definition corresponding to the <simpleType>
10593 * among the [children] of <list>.
10594 */
10595 return (type->subtypes->subtypes);
10596 else {
10597 /* 2 If the <restriction> option is chosen, then the
10598 * {item type definition} of the {base type definition}.
10599 */
10600 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10601 }
10602}
10603
10604/**
10605 * xmlSchemaCheckCOSSTDerivedOK:
10606 * @type: the derived simple type definition
10607 * @baseType: the base type definition
10608 *
10609 * Checks wheter @type can be validly
10610 * derived from @baseType.
10611 *
10612 * Returns 0 on success, an positive error code otherwise.
10613 */
10614static int
10615xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10616 xmlSchemaTypePtr type,
10617 xmlSchemaTypePtr baseType,
10618 int subset)
10619{
10620 /*
10621 * Schema Component Constraint: Type Derivation OK (Simple)
10622 *
10623 *
10624 * 1 They are the same type definition.
10625 * TODO: The identy check might have to be more complex than this.
10626 */
10627 if (type == baseType)
10628 return (0);
10629 /*
10630 * 2.1 restriction is not in the subset, or in the {final}
10631 * of its own {base type definition};
10632 */
10633 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10634 (xmlSchemaTypeFinalContains(schema,
10635 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10636 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10637 }
10638 /* 2.2 */
10639 if (type->baseType == baseType) {
10640 /*
10641 * 2.2.1 D's ·base type definition· is B.
10642 */
10643 return (0);
10644 }
10645 /*
10646 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10647 * and is validly derived from B given the subset, as defined by this
10648 * constraint.
10649 */
10650 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10651 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10652 return (0);
10653 }
10654 /*
10655 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10656 * definition·.
10657 */
10658 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10659 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10660 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10661 return (0);
10662 }
10663 /*
10664 * 2.2.4 B's {variety} is union and D is validly derived from a type
10665 * definition in B's {member type definitions} given the subset, as
10666 * defined by this constraint.
10667 *
10668 * NOTE: This seems not to involve built-in types, since there is no
10669 * built-in Union Simple Type.
10670 */
10671 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10672 xmlSchemaTypeLinkPtr cur;
10673
10674 cur = baseType->memberTypes;
10675 while (cur != NULL) {
10676 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10677 cur->type, subset) == 0)
10678 return (0);
10679 cur = cur->next;
10680 }
10681 }
10682
10683 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10684}
10685
10686
10687/**
10688 * xmlSchemaCheckSTPropsCorrect:
10689 * @ctxt: the schema parser context
10690 * @type: the simple type definition
10691 *
10692 * Checks st-props-correct.
10693 *
10694 * Returns 0 if the properties are correct,
10695 * if not, a positive error code and -1 on internal
10696 * errors.
10697 */
10698static int
10699xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10700 xmlSchemaTypePtr type)
10701{
10702 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10703 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010704 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010705
Daniel Veillardc0826a72004-08-10 14:17:33 +000010706 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010707 /*
10708 * Schema Component Constraint: Simple Type Definition Properties Correct
10709 *
10710 * NOTE: This is somehow redundant, since we actually built a simple type
10711 * to have all the needed information; this acts as an self test.
10712 */
10713 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10714 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10715 /*
10716 * TODO: 1 The values of the properties of a simple type definition must be as
10717 * described in the property tableau in Datatype definition, modulo the
10718 * impact of Missing Sub-components (§5.3).
10719 */
10720 /* Base type: If the datatype has been ·derived· by ·restriction·
10721 * then the Simple Type Definition component from which it is ·derived·,
10722 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10723 */
10724 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010725 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010726 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010727 NULL, type, NULL,
10728 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010729 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10730 }
10731 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10732 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10733 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010734 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010735 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010736 NULL, type, NULL,
10737 "The base type %s is not a simple type",
10738 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10739 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010740 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10741 }
10742 if ((baseType != anySimpleType) &&
10743 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010744 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010745 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010746 NULL, type, NULL,
10747 "A type, derived by list or union, must have"
10748 "the simple ur-type definition as base type, not %s",
10749 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10750 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010751 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10752 }
10753 /*
10754 * Variety: One of {atomic, list, union}.
10755 */
10756 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10757 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10758 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010759 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010760 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010761 NULL, type, NULL,
10762 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010763 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10764 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010765 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010766
10767 /*
10768 * 2 All simple type definitions must be derived ultimately from the ·simple
10769 * ur-type definition (so· circular definitions are disallowed). That is, it
10770 * must be possible to reach a built-in primitive datatype or the ·simple
10771 * ur-type definition· by repeatedly following the {base type definition}.
10772 */
10773 baseType = type->baseType;
10774 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10775 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10776 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10777 if (baseType == anySimpleType)
10778 break;
10779 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010780 xmlSchemaPCustomErr(ctxt,
10781 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10782 NULL, type, NULL,
10783 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010784 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10785 }
10786 baseType = baseType->baseType;
10787 }
10788 /*
10789 * 3 The {final} of the {base type definition} must not contain restriction.
10790 */
10791 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10792 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010793 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010794 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010795 NULL, type, NULL,
10796 "The 'final' of its base type %s must not contain "
10797 "'restriction'",
10798 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10799 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010800 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10801 }
10802 return (0);
10803}
10804
10805/**
10806 * xmlSchemaCheckDerivationValidSimpleRestriction:
10807 * @ctxt: the schema parser context
10808 * @type: the simple type definition
10809 *
10810 * Checks if the given @type (simpleType) is derived
10811 * validly by restriction.
10812 *
10813 * Returns -1 on internal errors, 0 if the type is validly derived,
10814 * a positive error code otherwise.
10815 */
10816static int
10817xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010818 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010819{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010820 xmlChar *str = NULL;
10821
10822 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010823
10824 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10825 xmlSchemaPErr(ctxt, type->node,
10826 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010827 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10828 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010829 type->name, NULL);
10830 return (-1);
10831 }
10832
10833 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10834 xmlSchemaTypePtr primitive;
10835 /*
10836 * 1.1 The {base type definition} must be an atomic simple
10837 * type definition or a built-in primitive datatype.
10838 */
10839 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010840 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010841 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010842 NULL, type, NULL,
10843 "The base type %s is not an atomic simple type",
10844 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10845 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010846 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10847 }
10848 /* 1.2 The {final} of the {base type definition} must not contain
10849 * restriction.
10850 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010851 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010852 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10853 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010854 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010855 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010856 NULL, type, NULL,
10857 "The final of its base type %s must not contain 'restriction'",
10858 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10859 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010860 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10861 }
10862
10863 /*
10864 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10865 * type definition}, as specified in the appropriate subsection of 3.2
10866 * Primitive datatypes.
10867 */
10868 if (type->facets != NULL) {
10869 xmlSchemaFacetPtr facet;
10870 int ok = 1;
10871
10872 primitive = xmlSchemaGetPrimitiveType(type);
10873 if (primitive == NULL) {
10874 xmlSchemaPErr(ctxt, type->node,
10875 XML_ERR_INTERNAL_ERROR,
10876 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010877 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010878 type->name, NULL);
10879 return (-1);
10880 }
10881 facet = type->facets;
10882 do {
10883 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010884 ok = 0;
10885 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010886 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010887 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010888 }
10889 facet = facet->next;
10890 } while (facet != NULL);
10891 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010892 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010893 }
10894 /*
10895 * TODO: 1.3.2 (facet derivation)
10896 */
10897 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10898 xmlSchemaTypePtr itemType = NULL;
10899
10900 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10901 if (itemType == NULL) {
10902 xmlSchemaPErr(ctxt, type->node,
10903 XML_ERR_INTERNAL_ERROR,
10904 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010905 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010906 type->name, NULL);
10907 return (-1);
10908 }
10909 /*
10910 * 2.1 The {item type definition} must have a {variety} of atomic or
10911 * union (in which case all the {member type definitions}
10912 * must be atomic).
10913 */
10914 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10915 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010916 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010917 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010918 NULL, type, NULL,
10919 "The item type %s must have a variety of atomic or union",
10920 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10921 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010922 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10923 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10924 xmlSchemaTypeLinkPtr member;
10925
10926 member = itemType->memberTypes;
10927 while (member != NULL) {
10928 if ((member->type->flags &
10929 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010930 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010931 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010932 NULL, type, NULL,
10933 "The item type is a union type, but the "
10934 "member type %s of this item type is not atomic",
10935 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10936 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010937 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10938 }
10939 member = member->next;
10940 }
10941 }
10942
10943 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10944 xmlSchemaFacetPtr facet;
10945 /*
10946 * This is the case if we have: <simpleType><list ..
10947 */
10948 /*
10949 * 2.3.1
10950 * 2.3.1.1 The {final} of the {item type definition} must not
10951 * contain list.
10952 */
10953 if (xmlSchemaTypeFinalContains(ctxt->schema,
10954 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010955 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010956 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010957 NULL, type, NULL,
10958 "The final of its item type %s must not contain 'list'",
10959 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10960 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010961 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10962 }
10963 /*
10964 * 2.3.1.2 The {facets} must only contain the whiteSpace
10965 * facet component.
10966 */
10967 if (type->facets != NULL) {
10968 facet = type->facets;
10969 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010970 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10971 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010972 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010973 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010974 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10975 }
10976 facet = facet->next;
10977 } while (facet != NULL);
10978 }
10979 /*
10980 * TODO: Datatypes states:
10981 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10982 * whose ·lexical space· allows space (such as string or anyURI)or
10983 * a ·union· datatype any of whose {member type definitions}'s
10984 * ·lexical space· allows space.
10985 */
10986 } else {
10987 /*
10988 * This is the case if we have: <simpleType><restriction ...
10989 */
10990 /*
10991 * 2.3.2
10992 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10993 */
10994 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010995 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010996 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010997 NULL, type, NULL,
10998 "The base type %s must be a list type",
10999 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11000 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011001 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11002 }
11003 /*
11004 * 2.3.2.2 The {final} of the {base type definition} must not
11005 * contain restriction.
11006 */
11007 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11008 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011009 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011010 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011011 NULL, type, NULL,
11012 "The final of the base type %s must not contain 'restriction'",
11013 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11014 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011015 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11016 }
11017 /*
11018 * 2.3.2.3 The {item type definition} must be validly derived
11019 * from the {base type definition}'s {item type definition} given
11020 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11021 */
11022 {
11023 xmlSchemaTypePtr baseItemType;
11024
11025 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11026 if (baseItemType == NULL) {
11027 xmlSchemaPErr(ctxt, type->node,
11028 XML_ERR_INTERNAL_ERROR,
11029 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011030 "List simple type '%s': Failed to "
11031 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011032 type->name, type->baseType->name);
11033 return (-1);
11034 }
11035 if ((itemType != baseItemType) &&
11036 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11037 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011038 xmlChar *strBIT = NULL, *strBT = NULL;
11039 xmlSchemaPCustomErrExt(ctxt,
11040 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11041 NULL, type, NULL,
11042 "The item type %s is not validly derived from the "
11043 "item type %s of the base type %s",
11044 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11045 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11046 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11047
11048 FREE_AND_NULL(str)
11049 FREE_AND_NULL(strBIT)
11050 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011051 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11052 }
11053 }
11054
11055 if (type->facets != NULL) {
11056 xmlSchemaFacetPtr facet;
11057 int ok = 1;
11058 /*
11059 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11060 * and enumeration facet components are allowed among the {facets}.
11061 */
11062 facet = type->facets;
11063 do {
11064 switch (facet->type) {
11065 case XML_SCHEMA_FACET_LENGTH:
11066 case XML_SCHEMA_FACET_MINLENGTH:
11067 case XML_SCHEMA_FACET_MAXLENGTH:
11068 case XML_SCHEMA_FACET_WHITESPACE:
11069 /*
11070 * TODO: 2.5.1.2 List datatypes
11071 * The value of ·whiteSpace· is fixed to the value collapse.
11072 */
11073 case XML_SCHEMA_FACET_PATTERN:
11074 case XML_SCHEMA_FACET_ENUMERATION:
11075 break;
11076 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011077 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011078 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011079 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011080 /*
11081 * We could return, but it's nicer to report all
11082 * invalid facets.
11083 */
11084 ok = 0;
11085 }
11086 }
11087 facet = facet->next;
11088 } while (facet != NULL);
11089 if (ok == 0)
11090 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11091 /*
11092 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11093 * is a facet of the same kind in the {facets} of the {base type
11094 * definition} (call this BF),then the DF's {value} must be a valid
11095 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11096 */
11097 }
11098
11099
11100 }
11101 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11102 /*
11103 * 3.1 The {member type definitions} must all have {variety} of
11104 * atomic or list.
11105 */
11106 xmlSchemaTypeLinkPtr member;
11107
11108 member = type->memberTypes;
11109 while (member != NULL) {
11110 if (((member->type->flags &
11111 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11112 ((member->type->flags &
11113 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011114 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011115 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 NULL, type, NULL,
11117 "The member type %s is neither an atomic, nor a list type",
11118 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11119 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011120 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11121 }
11122 member = member->next;
11123 }
11124 /*
11125 * 3.3.1 If the {base type definition} is the ·simple ur-type
11126 * definition·
11127 */
11128 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11129 /*
11130 * 3.3.1.1 All of the {member type definitions} must have a
11131 * {final} which does not contain union.
11132 */
11133 member = type->memberTypes;
11134 while (member != NULL) {
11135 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11136 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011137 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011138 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 NULL, type, NULL,
11140 "The final of member type %s contains 'union'",
11141 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11142 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011143 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11144 }
11145 member = member->next;
11146 }
11147 /*
11148 * 3.3.1.2 The {facets} must be empty.
11149 */
11150 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011151 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011152 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011153 NULL, type, NULL,
11154 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011155 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11156 }
11157 } else {
11158 /*
11159 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11160 */
11161 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011162 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011163 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011164 NULL, type, NULL,
11165 "The base type %s is not a union type",
11166 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11167 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011168 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11169 }
11170 /*
11171 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11172 */
11173 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11174 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011175 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011176 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011177 NULL, type, NULL,
11178 "The final of its base type %s must not contain 'restriction'",
11179 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11180 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011181 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11182 }
11183 /*
11184 * 3.3.2.3 The {member type definitions}, in order, must be validly
11185 * derived from the corresponding type definitions in the {base
11186 * type definition}'s {member type definitions} given the empty set,
11187 * as defined in Type Derivation OK (Simple) (§3.14.6).
11188 */
11189 {
11190 xmlSchemaTypeLinkPtr baseMember;
11191
11192 /*
11193 * OPTIMIZE: if the type is restricting, it has no local defined
11194 * member types and inherits the member types of the base type;
11195 * thus a check for equality can be skipped.
11196 */
11197 /*
11198 * TODO: Even worse: I cannot see a scenario where a restricting
11199 * union simple type can have other member types as the member
11200 * types of it's base type. This check seems not necessary with
11201 * respect to the derivation process in libxml2.
11202 */
11203 if (type->memberTypes != NULL) {
11204 member = type->memberTypes;
11205 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11206 if ((member == NULL) && (baseMember != NULL)) {
11207 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011208 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011209 "Internal error: "
11210 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011211 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011212 "of member types in the base type\n",
11213 type->name, NULL);
11214 }
11215 while (member != NULL) {
11216 if (baseMember == NULL) {
11217 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011218 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011219 "Internal error: "
11220 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011221 "(3.3.2.3), union simple type '%s', unequal number "
11222 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011223 type->name, NULL);
11224 }
11225 if ((member->type != baseMember->type) &&
11226 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11227 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011228 xmlChar *strBMT = NULL, *strBT = NULL;
11229
11230 xmlSchemaPCustomErrExt(ctxt,
11231 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11232 NULL, type, NULL,
11233 "The member type %s is not validly derived from its "
11234 "corresponding member type %s of the base type %s",
11235 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11236 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11237 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11238 FREE_AND_NULL(str)
11239 FREE_AND_NULL(strBMT)
11240 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011241 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11242 }
11243 member = member->next;
11244 baseMember = baseMember->next;
11245 }
11246 }
11247 }
11248 /*
11249 * 3.3.2.4 Only pattern and enumeration facet components are
11250 * allowed among the {facets}.
11251 */
11252 if (type->facets != NULL) {
11253 xmlSchemaFacetPtr facet;
11254 int ok = 1;
11255
11256 facet = type->facets;
11257 do {
11258 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11259 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011260 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11261 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11262 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011263 ok = 0;
11264 }
11265 facet = facet->next;
11266 } while (facet != NULL);
11267 if (ok == 0)
11268 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11269
11270 }
11271 /*
11272 * TODO: 3.3.2.5 (facet derivation)
11273 */
11274 }
11275 }
11276
11277 return (0);
11278}
11279
11280/**
11281 * xmlSchemaCheckSRCSimpleType:
11282 * @ctxt: the schema parser context
11283 * @type: the simple type definition
11284 *
11285 * Checks crc-simple-type constraints.
11286 *
11287 * Returns 0 if the constraints are satisfied,
11288 * if not a positive error code and -1 on internal
11289 * errors.
11290 */
11291static int
11292xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11293 xmlSchemaTypePtr type)
11294{
11295 /*
11296 * NOTE: src-simple-type 2-4 are redundant, since the checks
11297 * were are done for the corresponding <restriction>, <list> and <union>
11298 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11299 * Maby this can be skipped in the future, if we get sure it's not needed.
11300 */
11301 if (type->subtypes == NULL) {
11302 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011303 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011304 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011305 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011306 type->name, NULL);
11307 return (-1);
11308 }
11309 /*
11310 * src-simple-type.1 The corresponding simple type definition, if any,
11311 * must satisfy the conditions set out in Constraints on Simple Type
11312 * Definition Schema Components (§3.14.6).
11313 */
11314 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11315 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11316 /*
11317 * TODO: Removed this, since it got annoying to get an
11318 * extra error report, if anything failed until now.
11319 * Enable this if needed.
11320 */
11321 /*
11322 xmlSchemaPErr(ctxt, type->node,
11323 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011324 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011325 "on simple type definitions.\n",
11326 type->name, NULL);
11327 */
11328 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11329 }
11330
11331 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11332 /*
11333 * src-simple-type.2 If the <restriction> alternative is chosen,
11334 * either it must have a base [attribute] or a <simpleType> among its
11335 * [children], but not both.
11336 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011337 /*
11338 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11339 * NOTE: This was removed, since this will be already handled
11340 * in the parse function for <restriction>.
11341 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011342 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11343 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11344 * an itemType [attribute] or a <simpleType> among its [children],
11345 * but not both.
11346 * NOTE: baseType is set to the local simple type definiton,
11347 * if existent, at parse time. This is a hack and not nice.
11348 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011349 /*
11350 * TODO: Remove this, and add the check to the parse function of <list>.
11351 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011352 if (((type->subtypes->base == NULL) &&
11353 (type->baseType == NULL)) ||
11354 ((type->subtypes->base != NULL) &&
11355 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011356 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011357 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011358 NULL, type, NULL,
11359 "Either the attribute 'itemType' or the <simpleType> child "
11360 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011361 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11362 }
11363
11364
11365 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11366 xmlSchemaTypeLinkPtr member;
11367 xmlSchemaTypePtr ancestor, anySimpleType;
11368
11369 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11370
11371 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11372 * the <union> alternative is chosen, there must not be any entries
11373 * in the memberTypes [attribute] at any depth which resolve to the
11374 * component corresponding to the <simpleType>.
11375 */
11376 member = type->memberTypes;
11377 while (member != NULL) {
11378 ancestor = member->type;
11379 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11380 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11381 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11382 if (ancestor == anySimpleType)
11383 break;
11384 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011385 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011386 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011387 NULL, type, NULL,
11388 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011389 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11390 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11391 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011392 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011393 * type as item type, which in turn has a list ST as member
11394 * type, we will assume this here as well, since this check
11395 * was not yet performed.
11396 */
11397
11398 }
11399 ancestor = ancestor->baseType;
11400 }
11401 member = member->next;
11402 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011403 }
11404
11405 return (0);
11406}
11407
William M. Brack2f2a6632004-08-20 23:09:47 +000011408#if 0 /* Not yet used code for CT schema validation */
11409static int
11410xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11411 const xmlChar * value,
11412 xmlSchemaTypePtr type,
11413 int fireErrors)
11414{
11415 int ret;
11416 /*
11417 * 3.14.4 Simple Type Definition Validation Rules
11418 * Validation Rule: String Valid
11419 */
11420 /*
11421 * 1 It is schema-valid with respect to that definition as defined
11422 * by Datatype Valid in [XML Schemas: Datatypes].
11423 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011424 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11425 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011426 return (ret);
11427 /*
11428 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11429 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11430 * the string must be a ·declared entity name·.
11431 */
11432 /*
11433 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11434 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11435 * then every whitespace-delimited substring of the string must be a ·declared
11436 * entity name·.
11437 */
11438 /*
11439 * 2.3 otherwise no further condition applies.
11440 */
11441
11442 return (0);
11443}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011444#endif
11445
William M. Brack2f2a6632004-08-20 23:09:47 +000011446
11447static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011448xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11449{
11450 if (vctxt->pctxt == NULL) {
11451 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11452 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11453 if (vctxt->pctxt == NULL) {
11454 xmlSchemaVErr(vctxt, NULL,
11455 XML_SCHEMAV_INTERNAL,
11456 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11457 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011458 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011459 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011460 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011461 /* TODO: Pass user data. */
11462 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11463 }
11464 return (0);
11465}
11466
11467static int
11468xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11469{
11470 if (ctxt->vctxt == NULL) {
11471 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11472 if (ctxt->vctxt == NULL) {
11473 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011474 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011475 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11476 "failed to create a temp. validation context.\n",
11477 NULL, NULL);
11478 return (-1);
11479 }
11480 /* TODO: Pass user data. */
11481 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11482 }
11483 return (0);
11484}
11485
11486/**
11487 * xmlSchemaCheckCOSValidDefault:
11488 * @ctxt: the schema parser context
11489 * @type: the simple type definition
11490 * @value: the default value
11491 * @node: an optional node (the holder of the value)
11492 *
11493 * Checks the "cos-valid-default" constraints.
11494 *
11495 * Returns 0 if the constraints are satisfied,
11496 * if not, a positive error code and -1 on internal
11497 * errors.
11498 */
11499static int
11500xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11501 xmlSchemaValidCtxtPtr vctxt,
11502 xmlSchemaTypePtr type,
11503 const xmlChar *value,
11504 xmlNodePtr node)
11505{
11506 int ret = 0;
11507
11508 /*
11509 * cos-valid-default:
11510 * Schema Component Constraint: Element Default Valid (Immediate)
11511 * For a string to be a valid default with respect to a type
11512 * definition the appropriate case among the following must be true:
11513 */
11514 /*
11515 * NOTE: This has to work without a given node (the holder of the
11516 * value), since it should work on the component, i.e. an underlying
11517 * DOM must not be mandatory.
11518 */
11519 if ((pctxt == NULL) || (vctxt == NULL)) {
11520 xmlSchemaPErr(pctxt, node,
11521 XML_SCHEMAP_INTERNAL,
11522 "Internal error: xmlSchemaCheckCOSValidDefault, "
11523 "bad arguments: the parser and/or validation context is "
11524 "missing.\n",
11525 NULL, NULL);
11526 return (-1);
11527 }
11528 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011529 /*
11530 * Complex type.
11531 *
11532 * 2.1 its {content type} must be a simple type definition or mixed.
11533 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011534 /*
11535 * TODO: Adjust this when the content type will be computed
11536 * correctly.
11537 */
11538 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11539 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11540 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11541 xmlSchemaPSimpleTypeErr(pctxt,
11542 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11543 NULL, NULL, node,
11544 type, NULL, NULL,
11545 "If the type of a constraint value is complex, its content "
11546 "type must be mixed or a simple type",
11547 NULL, NULL);
11548 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11549 }
11550 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011551 /*
11552 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11553 * particle must be ·emptiable· as defined by Particle Emptiable
11554 * (§3.9.6).
11555 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011556
William M. Brack2f2a6632004-08-20 23:09:47 +000011557 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011558 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011559 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011560 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011561 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011562 }
11563 /*
11564 * 1 If the type definition is a simple type definition, then the string
11565 * must be ·valid· with respect to that definition as defined by String
11566 * Valid (§3.14.4).
11567 *
11568 * AND
11569 *
11570 * 2.2.1 If the {content type} is a simple type definition, then the
11571 * string must be ·valid· with respect to that simple type definition
11572 * as defined by String Valid (§3.14.4).
11573 */
11574 vctxt->node = node;
11575 vctxt->cur = NULL;
11576 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11577 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11578 if (ret < 0) {
11579 xmlSchemaPErr(pctxt, node,
11580 /* NOTNICE: error code: This function will be used during
11581 * schema construction and xsi:type validation.
11582 */
11583 XML_SCHEMAP_INTERNAL,
11584 "Internal error: xmlSchemaCheckCOSValidDefault, "
11585 "while validating a value constaint value.\n",
11586 NULL, NULL);
11587
11588 }
11589 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011590}
11591
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011592#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011593/**
11594 * xmlSchemaGetSTContentOfCT:
11595 * @ctxt: the schema parser context
11596 * @type: the complex type definition
11597 *
11598 *
11599 * Returns the corresponding simple type for the content of
11600 * the complex type.
11601 */
11602static xmlSchemaTypePtr
11603xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11604 xmlSchemaTypePtr type)
11605{
11606 xmlSchemaTypePtr orig = type, anyType;
11607
11608 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11609 while ((type != NULL) && (type != anyType) &&
11610 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11611 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11612 return(type);
11613 type = type->baseType;
11614 }
11615 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011616 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011617 NULL, orig, NULL,
11618 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11619 "no simple type for the content of complex type '%s' could be "
11620 "computed", orig->name);
11621 return (NULL);
11622}
11623
11624
William M. Brack2f2a6632004-08-20 23:09:47 +000011625
William M. Brack2f2a6632004-08-20 23:09:47 +000011626
11627/**
11628 * xmlSchemaCheckCOSCTExtends:
11629 * @ctxt: the schema parser context
11630 * @type: the complex type definition
11631 *
11632 * Schema Component Constraint: Derivation Valid (Extension)
11633 *
11634 * Returns 0 if the constraints are satisfied, a positive
11635 * error code if not and -1 if an internal error occured.
11636 */
11637static int
11638xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11639 xmlSchemaTypePtr type)
11640{
11641 xmlSchemaTypePtr base;
11642 /*
11643 * 1 If the {base type definition} is a complex type definition,
11644 * then all of the following must be true:
11645 */
11646 base = type->baseType;
11647 if (base == NULL) {
11648 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011649 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011650 NULL, type, NULL,
11651 "Internal error: xmlSchemaCheckCOSCTExtends, "
11652 "the complex type '%s' has no base type", type->name);
11653 return (-1);
11654 }
11655 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11656 /*
11657 * 1.1 The {final} of the {base type definition} must not
11658 * contain extension.
11659 */
11660 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11661 xmlSchemaPCustomErr(ctxt,
11662 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11663 NULL, type, NULL,
11664 "The 'final' of the base type definition "
11665 "contains extension", NULL);
11666 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11667 }
11668 /*
11669 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11670 * of the complex type definition itself, that is, for every attribute
11671 * use in the {attribute uses} of the {base type definition}, there
11672 * must be an attribute use in the {attribute uses} of the complex
11673 * type definition itself whose {attribute declaration} has the same
11674 * {name}, {target namespace} and {type definition} as its attribute
11675 * declaration
11676 *
11677 * NOTE: This will be already satisfied by the way the attribute uses
11678 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11679 * is not needed.
11680 */
11681
11682 /*
11683 * 1.3 If it has an {attribute wildcard}, the complex type definition
11684 * must also have one, and the base type definition's {attribute
11685 * wildcard}'s {namespace constraint} must be a subset of the complex
11686 * type definition's {attribute wildcard}'s {namespace constraint},
11687 * as defined by Wildcard Subset (§3.10.6).
11688 *
11689 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11690 * this check is not needed.
11691 */
11692
11693 /*
11694 * 1.4 One of the following must be true:
11695 *
11696 * 1.4.1 The {content type} of the {base type definition} and the
11697 * {content type} of the complex type definition itself must be the same
11698 * simple type definition
11699 */
11700
11701
11702
11703 } else {
11704 /*
11705 * 2 If the {base type definition} is a simple type definition,
11706 * then all of the following must be true:
11707 */
11708 /*
11709 * 2.1 The {content type} must be the same simple type definition.
11710 */
11711 /*
11712 * 2.2 The {final} of the {base type definition} must not contain
11713 * extension
11714 */
11715 }
11716
11717}
11718
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011719static int
11720xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11721 xmlSchemaTypePtr type)
11722{
11723 xmlSchemaTypePtr base, content;
11724 int OK = 0;
11725
11726 /*
11727 * TODO: Adjust the error codes here, as I used
11728 * XML_SCHEMAP_SRC_CT_1 only yet.
11729 */
11730 /*
11731 * Schema Representation Constraint:
11732 * Complex Type Definition Representation OK
11733 */
11734 base = type->baseType;
11735 if (base == NULL) {
11736 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11737 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11738 type->name);
11739 return (-1);
11740 }
11741
11742 if (type->subtypes != NULL) {
11743 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11744 if IS_COMPLEX_TYPE(base) {
11745 /*
11746 * 1 If the <complexContent> alternative is chosen, the type definition
11747 * ·resolved· to by the ·actual value· of the base [attribute]
11748 * must be a complex type definition;
11749 */
11750 xmlSchemaPCustomErr(ctxt,
11751 XML_SCHEMAP_SRC_CT_1,
11752 NULL, type, NULL,
11753 "The base type is not a complex type", NULL);
11754 return (XML_SCHEMAP_SRC_CT_1);
11755 }
11756 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11757
11758 if IS_SIMPLE_TYPE(base) {
11759 if (type->flags &
11760 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11761 /*
11762 * 2.1.3 only if the <extension> alternative is also
11763 * chosen, a simple type definition.
11764 */
11765 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11766 xmlSchemaPCustomErr(ctxt,
11767 XML_SCHEMAP_SRC_CT_1,
11768 NULL, type, NULL,
11769 "A complex type (simple content) cannot restrict "
11770 "an other simple type",
11771 NULL);
11772 return (XML_SCHEMAP_SRC_CT_1);
11773 }
11774 OK = 1;
11775
11776 } else { /* if IS_SIMPLE_TYPE(base) */
11777 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11778 /*
11779 * 2.1.2 only if the <restriction> alternative is also
11780 * chosen, a complex type definition whose {content type}
11781 * is mixed and a particle emptyable.
11782 */
11783 /*
11784 * FIXME TODO: Check for *empiable particle* is missing.
11785 */
11786 if ((type->flags &
11787 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11788 xmlSchemaPCustomErr(ctxt,
11789 XML_SCHEMAP_SRC_CT_1,
11790 NULL, type, NULL,
11791 "A complex type (simple content) cannot "
11792 "extend an other complex type which has a "
11793 "content type of: 'mixed' and emptiable particle",
11794 NULL);
11795 return (XML_SCHEMAP_SRC_CT_1);
11796 }
11797 /*
11798 * NOTE: This will be fired as well, if the base type
11799 * is *'anyType'*.
11800 * NOTE: type->subtypes->subtypes will be the
11801 * <restriction> item.
11802 */
11803 if (type->subtypes->subtypes == NULL) {
11804 /* Yes, this is paranoid programming. */
11805 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11806 NULL, type, NULL,
11807 "Internal error: xmlSchemaCheckSRCCT, "
11808 "'%s', <simpleContent> has no <restriction>",
11809 type->name);
11810 return (-1);
11811 }
11812 /*
11813 * 2.2 If clause 2.1.2 above is satisfied, then there
11814 * must be a <simpleType> among the [children] of
11815 * <restriction>.
11816 */
11817 if (type->subtypes->subtypes->type !=
11818 XML_SCHEMA_TYPE_SIMPLE) {
11819 /* TODO: Change error code to ..._SRC_CT_2_2. */
11820 xmlSchemaPCustomErr(ctxt,
11821 XML_SCHEMAP_SRC_CT_1,
11822 NULL, type, NULL,
11823 "A <simpleType> is expected among the children "
11824 "of <restriction>", NULL);
11825 return (XML_SCHEMAP_SRC_CT_1);
11826 }
11827 OK = 1;
11828 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
11829 /*
11830 * 2.1.1 a complex type definition whose {content type} is a
11831 * simple type definition;
11832 */
11833 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
11834 xmlSchemaPCustomErr(ctxt,
11835 XML_SCHEMAP_SRC_CT_1,
11836 NULL, type, NULL,
11837 "A complex type (simple content) cannot "
11838 "be derived from the complex type '%s'",
11839 base->name);
11840 return (XML_SCHEMAP_SRC_CT_1);
11841 }
11842 content = base->contentTypeDef;
11843 if (content == NULL) {
11844 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11845 NULL, type, NULL,
11846 "Internal error: xmlSchemaCheckSRCCT, "
11847 "'%s', base type has no content type",
11848 type->name);
11849 return (-1);
11850 }
11851 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
11852 xmlSchemaPCustomErr(ctxt,
11853 XML_SCHEMAP_SRC_CT_1,
11854 NULL, type, NULL,
11855 "A complex type (simple content) cannot "
11856 "be derived from the complex type '%s'",
11857 base->name);
11858 return (XML_SCHEMAP_SRC_CT_1);
11859 }
11860 }
11861 }
11862 }
11863 }
11864 /*
11865 * TODO: 3 The corresponding complex type definition component must
11866 * satisfy the conditions set out in Constraints on Complex Type
11867 * Definition Schema Components (§3.4.6);
11868 *
11869 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
11870 * above for {attribute wildcard} is satisfied, the intensional
11871 * intersection must be expressible, as defined in Attribute Wildcard
11872 * Intersection (§3.10.6).
11873 */
11874
11875}
William M. Brack2f2a6632004-08-20 23:09:47 +000011876#endif
11877
Daniel Veillard01fa6152004-06-29 17:04:39 +000011878/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011879 * xmlSchemaGroupDefFixup:
11880 * @typeDecl: the schema model group definition
11881 * @ctxt: the schema parser context
11882 *
11883 * Fixes model group definitions.
11884 */
11885static void
11886xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11887 xmlSchemaParserCtxtPtr ctxt,
11888 const xmlChar * name ATTRIBUTE_UNUSED)
11889{
11890 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11891 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11892 xmlSchemaTypePtr groupDef;
11893 /*
11894 * Resolve the reference.
11895 */
11896 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11897 group->refNs);
11898 if (groupDef == NULL) {
11899 xmlSchemaPResCompAttrErr(ctxt,
11900 XML_SCHEMAP_SRC_RESOLVE,
11901 NULL, group, NULL,
11902 "ref", group->ref, group->refNs,
11903 XML_SCHEMA_TYPE_GROUP, NULL);
11904 return;
11905 }
11906 group->subtypes = groupDef;
11907 }
11908}
11909
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011910#if 0 /* Enable when the content type will be computed. */
11911static int
11912xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
11913 xmlSchemaTypePtr type)
11914{
11915 xmlSchemaTypePtr base, res = NULL;
11916
11917 base = type->baseType;
11918 if (base == NULL) {
11919 xmlSchemaPCustomErr(ctxt,
11920 XML_SCHEMAP_INTERNAL,
11921 NULL, type, NULL,
11922 "Internal error: xmlSchemaGetContentType, "
11923 "the complex type '%s' has no base type", type->name);
11924 return (-1);
11925 }
11926 if (IS_ANYTYPE(base) || (type->subtypes->type ==
11927 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
11928 xmlSchemaTypePtr start;
11929 /*
11930 * Effective 'mixed'.
11931 */
11932 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
11933 type->contentType = XML_SCHEMA_CONTENT_MIXED;
11934 /*
11935 * Effective content.
11936 */
11937 if (IS_ANYTYPE(base))
11938 start = type;
11939 else
11940 start = type->subtypes;
11941
11942 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
11943 xmlSchemaTypePtr baseContentItem;
11944
11945 /*
11946 * Complex type with simple content.
11947 */
11948 if IS_COMPLEX_TYPE(base) {
11949 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11950 /*
11951 * Summary: a complex type (simple content) can *restrict*
11952 * a complex type with the following content type:
11953 * 1. 'mixed' and an emptiable particle
11954 * 2. simple type
11955 */
11956 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
11957 /*
11958 * 2 if the {content type} of the base type is mixed and a
11959 * particle which is ·emptiable·,
11960 * [...]
11961 * then starting from the simple type definition
11962 * corresponding to the <simpleType> among the [children]
11963 * of <restriction> (**which must be present**)
11964 *
11965 * FIXME TODO: Handle "emptiable particle".
11966 */
11967 res = type->subtypes->subtypes;
11968 if (res == NULL) {
11969 xmlSchemaPCustomErr(ctxt,
11970 XML_SCHEMAP_INTERNAL,
11971 NULL, type, NULL,
11972 "Internal error: xmlSchemaGetContentType, "
11973 "CT '%s' (restricting): <simpleContent> has no "
11974 "<restriction>",
11975 type->name);
11976 return (-1);
11977 }
11978
11979 res->subtypes;
11980 if (res == NULL) {
11981 xmlSchemaPCustomErr(ctxt,
11982 XML_SCHEMAP_INTERNAL,
11983 NULL, type, NULL,
11984 "Internal error: xmlSchemaGetContentType, "
11985 "CT '%s' (restricting): <restriction> has no "
11986 "mandatory <simpleType>",
11987 type->name);
11988 return (-1);
11989 }
11990 } else {
11991 baseContentItem = base->contentTypeDef;
11992 if (baseContentItem == NULL) {
11993 xmlSchemaPCustomErr(ctxt,
11994 XML_SCHEMAP_INTERNAL,
11995 NULL, type, NULL,
11996 "Internal error: xmlSchemaGetContentType, "
11997 "CT '%s' (restricting), the base type has no "
11998 "content type", type->name);
11999 return (-1);
12000 }
12001 if IS_SIMPLE_TYPE(baseContentItem) {
12002 /*
12003 * 1 If the base type is a complex type whose own
12004 * {content type} is a simple type and the <restriction>
12005 * alternative is chosen
12006 */
12007 /* type->subtypes->subtypes will be the restriction item.*/
12008 res = type->subtypes->subtypes;
12009 if (res == NULL) {
12010 xmlSchemaPCustomErr(ctxt,
12011 XML_SCHEMAP_INTERNAL,
12012 NULL, type, NULL,
12013 "Internal error: xmlSchemaGetContentType, "
12014 "CT '%s' (restricting): <simpleType> has no "
12015 "<restriction>", type->name);
12016 return (-1);
12017 }
12018 /*
12019 * 1.1 the simple type definition corresponding to the
12020 * <simpleType> among the [children] of <restriction>if
12021 * there is one;
12022 */
12023 res = res->subtypes;
12024 if (res == NULL) {
12025 /*
12026 * 1.2 otherwise the {content type}
12027 * of the base type .
12028 */
12029 res = baseContentItem;
12030 }
12031 }
12032 }
12033 /*
12034 * SPECIAL TODO: If *restricting* the spec wants us to
12035 * create an *additional* simple type which restricts the
12036 * located simple type; we won't do this yet, and look how
12037 * far we get with it.
12038 */
12039 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12040 /*
12041 * Summary: a complex type (simple content) can *extend*
12042 * only a complex base with a simple type as content.
12043 */
12044 /*
12045 * 3 If the type definition ·resolved· to by the ·actual
12046 * value· of the base [attribute] is a complex type
12047 * definition (whose own {content type} *must be* a simple
12048 * type definition, see below) and the *<extension>*
12049 * alternative is chosen, then the {content type} of that
12050 * complex type definition;
12051 */
12052 res = base->contentTypeDef;
12053 if (res == NULL) {
12054 xmlSchemaPCustomErr(ctxt,
12055 XML_SCHEMAP_INTERNAL,
12056 NULL, type, NULL,
12057 "Internal error: xmlSchemaGetContentType, "
12058 "CT '%s' (extending), the base type has no content "
12059 "type", type->name);
12060 return (-1);
12061 }
12062 if (! IS_SIMPLE_TYPE(res)) {
12063 xmlSchemaPCustomErr(ctxt,
12064 XML_SCHEMAP_INTERNAL,
12065 NULL, type, NULL,
12066 "Internal error: xmlSchemaGetContentType, "
12067 "CT '%s' (extending), the content type of the "
12068 "base is not a simple type", type->name);
12069 return (-1);
12070 }
12071 }
12072 } else /* if IS_COMPLEX_TYPE(base) */
12073 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12074 /*
12075 * 4 otherwise (the type definition ·resolved· to by the
12076 * ·actual value· of the base [attribute] is a simple type
12077 * definition and the <extension> alternative is chosen),
12078 * then that simple type definition.
12079 */
12080 res = base;
12081 }
12082 type->contentTypeDef = res;
12083 if (res == NULL) {
12084 xmlSchemaPCustomErr(ctxt,
12085 XML_SCHEMAP_INTERNAL,
12086 NULL, type, NULL,
12087 "Internal error: xmlSchemaGetContentType, "
12088 "'%s', the content type could not be determined",
12089 type->name);
12090 return (-1);
12091 }
12092
12093 }
12094
12095}
12096#endif
12097
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012098/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012099 * xmlSchemaTypeFixup:
12100 * @typeDecl: the schema type definition
12101 * @ctxt: the schema parser context
12102 *
12103 * Fixes the content model of the type.
12104 */
12105static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012106xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012107 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012108{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012109 xmlSchemaTypePtr ctxtType;
12110
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012111 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012112 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012113 /*
12114 * Do not allow the following types to be typefixed, prior to
12115 * the corresponding simple/complex types.
12116 */
12117 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012118 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012119 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12120 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12121 case XML_SCHEMA_TYPE_UNION:
12122 case XML_SCHEMA_TYPE_RESTRICTION:
12123 case XML_SCHEMA_TYPE_EXTENSION:
12124 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012125 default:
12126 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012127 }
12128 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012129 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012130 name = item->name;
12131 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12132 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012133 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012134 if (item->subtypes != NULL) {
12135 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012136 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012137 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012138 NULL);
12139 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012140 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012141 XML_SCHEMA_CONTENT_SIMPLE;
12142 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012143 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012144 break;
12145 }
12146 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012147 xmlSchemaTypePtr base = NULL;
12148
12149 ctxt->ctxtType->flags |=
12150 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012151 if (item->baseType != NULL)
12152 base = item->baseType;
12153 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012154 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012155 xmlSchemaGetType(ctxt->schema, item->base,
12156 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012157 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012158 xmlSchemaPResCompAttrErr(ctxt,
12159 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012160 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012161 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12162 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012163 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012164 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012165 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012166 xmlSchemaTypeFixup(base, ctxt, NULL);
12167 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012168 }
12169 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012170 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12171 /*
12172 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012173 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012174 /*
12175 * Content type.
12176 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012177 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012178 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012179 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12180 else if ((item->subtypes->subtypes == NULL) &&
12181 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012182 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012183 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012184 XML_SCHEMA_TYPE_SEQUENCE)))
12185 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012186 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12187 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012188 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012189 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012190 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012191 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012192 else {
12193 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012194 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012195 XML_SCHEMA_CONTENT_ELEMENTS;
12196 }
12197 } else {
12198 /*
12199 * SimpleType restriction.
12200 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012201 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012202 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012203 break;
12204 }
12205 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012206 xmlSchemaTypePtr base = NULL;
12207 xmlSchemaContentType explicitContentType;
12208
12209 /*
12210 * An extension does exist on a complexType only.
12211 */
12212 ctxt->ctxtType->flags |=
12213 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012214 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012215 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012216 xmlSchemaPCustomErr(ctxt,
12217 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012218 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012219 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012220 return;
12221 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012222 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012223 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012224 xmlSchemaGetType(ctxt->schema, item->base,
12225 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012226 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012227 xmlSchemaPResCompAttrErr(ctxt,
12228 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012229 NULL, item, item->node,
12230 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012231 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012232 } else if (base->contentType ==
12233 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012234 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012235 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012236 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012237 }
12238 /*
12239 * The type definition ·resolved· to by the ·actual
12240 * value· of the base [attribute]
12241 */
12242 ctxt->ctxtType->baseType = base;
12243 /*
12244 * TODO: This one is still needed for computation of
12245 * the content model by xmlSchemaBuildAContentModel.
12246 * Try to get rid of it.
12247 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012248 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012249 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012250 if ((item->subtypes != NULL) &&
12251 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12252 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012253
12254 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012255 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012256 /* 1.1.1 */
12257 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012258 else if ((item->subtypes->subtypes == NULL) &&
12259 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012260 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012261 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012262 XML_SCHEMA_TYPE_SEQUENCE)))
12263 /* 1.1.2 */
12264 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012265 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012266 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012267 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012268 /* 1.1.3 */
12269 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12270 if (base != NULL) {
12271 /* It will be reported later, if the base is missing. */
12272 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12273 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012274 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012275 } else if (base->contentType ==
12276 XML_SCHEMA_CONTENT_EMPTY) {
12277 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012278 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012279 XML_SCHEMA_CONTENT_ELEMENTS;
12280 } else {
12281 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012282 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012283 XML_SCHEMA_CONTENT_ELEMENTS;
12284 }
12285 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012286 break;
12287 }
12288 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012289 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012290 ctxt->ctxtType = item;
12291 /*
12292 * Start with an empty content-type type.
12293 */
12294 if (item->subtypes == NULL)
12295 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12296
12297 if ((item->subtypes == NULL) ||
12298 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012299 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012300 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012301 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12302 /*
12303 * This case is understood as shorthand for complex
12304 * content restricting the ur-type definition, and
12305 * the details of the mappings should be modified as
12306 * necessary.
12307 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012308 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12309 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012310 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012311 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012312 * Assume that we inherit the content-type type
12313 * from 'anyType', which is 'mixed' and a particle
12314 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012315 */
12316 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012317 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012318 /*
12319 * Fixup the sub components.
12320 */
12321 if ((item->subtypes != NULL) &&
12322 (item->subtypes->contentType ==
12323 XML_SCHEMA_CONTENT_UNKNOWN)) {
12324 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012325 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012326 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12327 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12328 } else if (item->subtypes != NULL) {
12329 /*
12330 * Use the content-type type of the model groups
12331 * defined, if 'mixed' is not set. If 'mixed' is set
12332 * it will expand the content-type by allowing character
12333 * content to appear.
12334 */
12335 item->contentType =
12336 item->subtypes->contentType;
12337 }
12338 xmlSchemaBuildAttributeValidation(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012339 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012340 break;
12341 }
12342 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012343 if (item->subtypes == NULL) {
12344 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12345 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12346 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012347 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012348 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012349 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12350 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012351 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012352 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012353 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012354 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012355 if (item->subtypes != NULL)
12356 item->contentType =
12357 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012358 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012359 /*
12360 * Removed due to implementation of the build of attribute uses.
12361 */
12362 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012363 if (item->attributes == NULL)
12364 item->attributes =
12365 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012366 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012367 }
12368 break;
12369 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012370 case XML_SCHEMA_TYPE_SIMPLE:
12371 /*
12372 * Simple Type Definition Schema Component
12373 *
12374 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012375 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012376 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12377 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012378 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012379 ctxt->ctxtType = item;
12380 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012381 }
12382 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012383 if ((item->baseType != NULL) &&
12384 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012385 XML_SCHEMA_CONTENT_UNKNOWN)) {
12386 /* OPTIMIZE: Actually this one will never by hit, since
12387 * the base type is already type-fixed in <restriction>.
12388 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012389 ctxt->ctxtType = item;
12390 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012391 }
12392 /* Base type:
12393 * 2 If the <list> or <union> alternative is chosen,
12394 * then the ·simple ur-type definition·.
12395 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012396 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012397 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012398 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12399 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12400 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012401 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012402 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12403 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12404 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012405 XML_SCHEMA_TYPE_RESTRICTION) {
12406 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12407
12408 /*
12409 * Variety
12410 * If the <restriction> alternative is chosen, then the
12411 * {variety} of the {base type definition}.
12412 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012413 if (item->baseType != NULL) {
12414 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012415 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12417 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012418 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012419 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12420 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012421 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012422 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012423 /*
12424 * Schema Component Constraint: Simple Type Restriction
12425 * (Facets)
12426 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12427 * applied beforehand.
12428 *
12429 * 3 The {facets} of R are the union of S and the {facets}
12430 * of B, eliminating duplicates. To eliminate duplicates,
12431 * when a facet of the same kind occurs in both S and the
12432 * {facets} of B, the one in the {facets} of B is not
12433 * included, with the exception of enumeration and pattern
12434 * facets, for which multiple occurrences with distinct values
12435 * are allowed.
12436 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012437 if (item->baseType->facetSet != NULL) {
12438 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012439 if (last != NULL)
12440 while (last->next != NULL)
12441 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012442 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012443 for (; cur != NULL; cur = cur->next) {
12444 /*
12445 * Base patterns won't be add here:
12446 * they are ORed in a type and
12447 * ANDed in derived types. This will
12448 * happed at validation level by
12449 * walking the base axis of the type.
12450 */
12451 if (cur->facet->type ==
12452 XML_SCHEMA_FACET_PATTERN)
12453 continue;
12454 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012455 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012456 (cur->facet->type !=
12457 XML_SCHEMA_FACET_PATTERN) &&
12458 (cur->facet->type !=
12459 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012460 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012461 do {
12462 if (cur->facet->type ==
12463 facet->facet->type)
12464 break;
12465 facet = facet->next;
12466 } while (facet != NULL);
12467 }
12468 if (facet == NULL) {
12469 facet = (xmlSchemaFacetLinkPtr)
12470 xmlMalloc(sizeof(xmlSchemaFacetLink));
12471 if (facet == NULL) {
12472 xmlSchemaPErrMemory(ctxt,
12473 "fixing simpleType", NULL);
12474 return;
12475 }
12476 facet->facet = cur->facet;
12477 facet->next = NULL;
12478 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012479 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012480 else
12481 last->next = facet;
12482 last = facet;
12483 }
12484 }
12485 }
12486 }
12487 }
12488 /*
12489 * Check constraints.
12490 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012491 xmlSchemaCheckSRCSimpleType(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012492 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012493 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012494 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012495 case XML_SCHEMA_TYPE_ALL:
12496 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012497 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012498 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012499 case XML_SCHEMA_TYPE_GROUP:
12500 /*
12501 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12502 */
12503 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012504 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012505 xmlSchemaParseListRefFixup(item, ctxt);
12506 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012507 break;
12508 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012509 xmlSchemaParseUnionRefCheck(item, ctxt);
12510 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012511 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012512 case XML_SCHEMA_TYPE_BASIC:
12513 case XML_SCHEMA_TYPE_ANY:
12514 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012515 case XML_SCHEMA_TYPE_UR:
12516 case XML_SCHEMA_TYPE_ELEMENT:
12517 case XML_SCHEMA_TYPE_ATTRIBUTE:
12518 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012519 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012520 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012521 case XML_SCHEMA_FACET_MININCLUSIVE:
12522 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12523 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12524 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12525 case XML_SCHEMA_FACET_TOTALDIGITS:
12526 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12527 case XML_SCHEMA_FACET_PATTERN:
12528 case XML_SCHEMA_FACET_ENUMERATION:
12529 case XML_SCHEMA_FACET_WHITESPACE:
12530 case XML_SCHEMA_FACET_LENGTH:
12531 case XML_SCHEMA_FACET_MAXLENGTH:
12532 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012533 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12534 if (item->subtypes != NULL)
12535 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012536 break;
12537 }
12538 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012539#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012540 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012541 xmlGenericError(xmlGenericErrorContext,
12542 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012543 item->node->doc->URL,
12544 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012545 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012546 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012547 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012548 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012549 case XML_SCHEMA_CONTENT_SIMPLE:
12550 xmlGenericError(xmlGenericErrorContext, "simple\n");
12551 break;
12552 case XML_SCHEMA_CONTENT_ELEMENTS:
12553 xmlGenericError(xmlGenericErrorContext, "elements\n");
12554 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012555 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012556 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12557 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012558 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012559 xmlGenericError(xmlGenericErrorContext, "empty\n");
12560 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012561 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012562 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12563 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012564 /* Removed, since not used. */
12565 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012566 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012567 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12568 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012569 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012570 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012571 xmlGenericError(xmlGenericErrorContext, "basic\n");
12572 break;
12573 default:
12574 xmlGenericError(xmlGenericErrorContext,
12575 "not registered !!!\n");
12576 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012577 }
12578#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012579}
12580
12581/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012582 * xmlSchemaCheckFacet:
12583 * @facet: the facet
12584 * @typeDecl: the schema type definition
12585 * @ctxt: the schema parser context or NULL
12586 * @name: name of the type
12587 *
12588 * Checks the default values types, especially for facets
12589 *
12590 * Returns 0 if okay or -1 in cae of error
12591 */
12592int
12593xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012594 xmlSchemaTypePtr typeDecl,
12595 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012596{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012597 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012598 int ret = 0, reuseValCtxt = 0;
12599
Daniel Veillardce682bc2004-11-05 17:22:25 +000012600 if ((facet == NULL) || (typeDecl == NULL))
12601 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012602 /*
12603 * TODO: will the parser context be given if used from
12604 * the relaxNG module?
12605 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012606
12607 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012608 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012609 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012610 }
12611 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012612 case XML_SCHEMA_FACET_MININCLUSIVE:
12613 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12614 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012615 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12616 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012617 /*
12618 * Okay we need to validate the value
12619 * at that point.
12620 */
12621 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012622 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012623
12624 /* 4.3.5.5 Constraints on enumeration Schema Components
12625 * Schema Component Constraint: enumeration valid restriction
12626 * It is an ·error· if any member of {value} is not in the
12627 * ·value space· of {base type definition}.
12628 *
12629 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12630 * The value ·must· be in the
12631 * ·value space· of the ·base type·.
12632 */
12633 /*
12634 * This function is intended to deliver a compiled value
12635 * on the facet. In XML Schemas the type holding a facet,
12636 * cannot be a built-in type. Thus to ensure that other API
12637 * calls (relaxng) do work, if the given type is a built-in
12638 * type, we will assume that the given built-in type *is
12639 * already* the base type.
12640 */
12641 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12642 base = typeDecl->baseType;
12643 if (base == NULL) {
12644 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012645 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012646 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012647 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012648 typeDecl->name, NULL);
12649 return (-1);
12650 }
12651 } else
12652 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012653 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012654 * This avoids perseverative creation of the
12655 * validation context if a parser context is
12656 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012657 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012658 if (ctxt != NULL) {
12659 reuseValCtxt = 1;
12660 if (ctxt->vctxt == NULL) {
12661 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12662 return (-1);
12663 }
12664 vctxt = ctxt->vctxt;
12665 } else {
12666 vctxt = xmlSchemaNewValidCtxt(NULL);
12667 if (vctxt == NULL) {
12668 xmlSchemaPErr(ctxt, typeDecl->node,
12669 XML_SCHEMAP_INTERNAL,
12670 "Internal error: xmlSchemaCheckFacet, "
12671 "creating a new validation context.\n",
12672 NULL, NULL);
12673 return (-1);
12674 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012675 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012676
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012677 vctxt->node = facet->node;
12678 vctxt->cur = NULL;
12679 /*
12680 * NOTE: This call does not check the content nodes,
12681 * since they are not available:
12682 * facet->node is just the node holding the facet
12683 * definition, *not* the attribute holding the *value*
12684 * of the facet.
12685 */
12686 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12687 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012688 facet->val = vctxt->value;
12689 vctxt->value = NULL;
12690 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012691 /* error code */
12692 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012693 xmlSchemaPErrExt(ctxt, facet->node,
12694 XML_SCHEMAP_INVALID_FACET,
12695 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012696 "Type definition '%s': The value '%s' of the "
12697 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012698 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012699 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012700 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012701 }
12702 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012703 } else if (ret < 0) {
12704 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012705 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012706 NULL, NULL, NULL,
12707 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012708 "failed to validate the value '%s' name of the "
12709 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012710 facet->value,
12711 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12712 base->name, NULL, NULL);
12713 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012714 }
12715 if (reuseValCtxt == 0)
12716 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012717 break;
12718 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012719 case XML_SCHEMA_FACET_PATTERN:
12720 facet->regexp = xmlRegexpCompile(facet->value);
12721 if (facet->regexp == NULL) {
12722 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012723 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012724 "Type definition '%s': The value '%s' of the "
12725 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012726 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012727 ret = -1;
12728 }
12729 break;
12730 case XML_SCHEMA_FACET_TOTALDIGITS:
12731 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12732 case XML_SCHEMA_FACET_LENGTH:
12733 case XML_SCHEMA_FACET_MAXLENGTH:
12734 case XML_SCHEMA_FACET_MINLENGTH:{
12735 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012736
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012737 tmp =
12738 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12739 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012740 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012741 if (tmp != 0) {
12742 /* error code */
12743 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012744 xmlSchemaPErrExt(ctxt, facet->node,
12745 XML_SCHEMAP_INVALID_FACET_VALUE,
12746 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012747 "Type definition '%s': The value '%s' of the "
12748 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012749 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012750 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012751 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012752 }
12753 ret = -1;
12754 }
12755 break;
12756 }
12757 case XML_SCHEMA_FACET_WHITESPACE:{
12758 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12759 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12760 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12761 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12762 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12763 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12764 } else {
12765 if (ctxt != NULL) {
12766 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012767 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012768 "Type definition '%s': The value '%s' of the "
12769 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012770 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012771 }
12772 ret = -1;
12773 }
12774 }
12775 default:
12776 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012777 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012778 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012779}
12780
12781/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012782 * xmlSchemaCheckDefaults:
12783 * @typeDecl: the schema type definition
12784 * @ctxt: the schema parser context
12785 *
12786 * Checks the default values types, especially for facets
12787 */
12788static void
12789xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012790 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012791{
Daniel Veillard4255d502002-04-16 15:50:10 +000012792 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012793 name = typeDecl->name;
12794 /*
12795 * NOTE: It is intended to use the facets list, instead
12796 * of facetSet.
12797 */
12798 if (typeDecl->facets != NULL) {
12799 xmlSchemaFacetPtr facet = typeDecl->facets;
12800
12801 while (facet != NULL) {
12802 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12803 facet = facet->next;
12804 }
12805 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012806}
12807
12808/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012809 * xmlSchemaGetCircModelGrDefRef:
12810 * @ctxtGr: the searched model group
12811 * @list: the list of model groups to be processed
12812 *
12813 * This one is intended to be used by
12814 * xmlSchemaCheckGroupDefCircular only.
12815 *
12816 * Returns the circular model group definition reference, otherwise NULL.
12817 */
12818static xmlSchemaTypePtr
12819xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12820 xmlSchemaTypePtr gr)
12821{
12822 xmlSchemaTypePtr circ = NULL;
12823 int marked;
12824 /*
12825 * We will search for an model group reference which
12826 * references the context model group definition.
12827 */
12828 while (gr != NULL) {
12829 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
12830 (gr->type == XML_SCHEMA_TYPE_ALL) ||
12831 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
12832 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
12833 (gr->subtypes != NULL)) {
12834 marked = 0;
12835 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
12836 (gr->ref != NULL)) {
12837 if (gr->subtypes == ctxtGrDef)
12838 return (gr);
12839 else if (gr->subtypes->flags &
12840 XML_SCHEMAS_TYPE_MARKED) {
12841 gr = gr->next;
12842 continue;
12843 } else {
12844 /*
12845 * Mark to avoid infinite recursion on
12846 * circular references not yet examined.
12847 */
12848 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
12849 marked = 1;
12850 }
12851 if (gr->subtypes->subtypes != NULL)
12852 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12853 gr->subtypes->subtypes);
12854 /*
12855 * Unmark the visited model group definition.
12856 */
12857 if (marked)
12858 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
12859 if (circ != NULL)
12860 return (circ);
12861 } else {
12862 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12863 (xmlSchemaTypePtr) gr->subtypes);
12864 if (circ != NULL)
12865 return (circ);
12866 }
12867
12868 }
12869 gr = gr->next;
12870 }
12871 return (NULL);
12872}
12873
12874/**
12875 * xmlSchemaCheckGroupDefCircular:
12876 * attrGr: the model group definition
12877 * @ctxt: the parser context
12878 * @name: the name
12879 *
12880 * Checks for circular references to model group definitions.
12881 */
12882static void
12883xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
12884 xmlSchemaParserCtxtPtr ctxt,
12885 const xmlChar * name ATTRIBUTE_UNUSED)
12886{
12887 /*
12888 * Schema Component Constraint: Model Group Correct
12889 * 2 Circular groups are disallowed. That is, within the {particles}
12890 * of a group there must not be at any depth a particle whose {term}
12891 * is the group itself.
12892 */
12893 /*
12894 * NOTE: "gr->subtypes" holds the referenced group.
12895 */
12896 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
12897 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
12898 (modelGrDef->subtypes == NULL))
12899 return;
12900 else {
12901 xmlSchemaTypePtr circ;
12902
12903 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
12904 if (circ != NULL) {
12905 /*
12906 * TODO: Report the referenced attr group as QName.
12907 */
12908 xmlSchemaPCustomErr(ctxt,
12909 XML_SCHEMAP_MG_PROPS_CORRECT_2,
12910 NULL, NULL, circ->node,
12911 "Circular reference to the model group definition '%s' "
12912 "defined", modelGrDef->name);
12913 /*
12914 * NOTE: We will cut the reference to avoid further
12915 * confusion of the processor.
12916 * TODO: SPEC: Does the spec define how to process here?
12917 */
12918 circ->subtypes = NULL;
12919 }
12920 }
12921}
12922
12923
12924/**
12925 * xmlSchemaGetCircAttrGrRef:
12926 * @ctxtGr: the searched attribute group
12927 * @attr: the current attribute list to be processed
12928 *
12929 * This one is intended to be used by
12930 * xmlSchemaCheckSRCAttributeGroupCircular only.
12931 *
12932 * Returns the circular attribute grou reference, otherwise NULL.
12933 */
12934static xmlSchemaAttributeGroupPtr
12935xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
12936 xmlSchemaAttributePtr attr)
12937{
12938 xmlSchemaAttributeGroupPtr circ = NULL, gr;
12939 int marked;
12940 /*
12941 * We will search for an attribute group reference which
12942 * references the context attribute group.
12943 */
12944 while (attr != NULL) {
12945 marked = 0;
12946 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12947 gr = (xmlSchemaAttributeGroupPtr) attr;
12948 if (gr->refItem != NULL) {
12949 if (gr->refItem == ctxtGr)
12950 return (gr);
12951 else if (gr->refItem->flags &
12952 XML_SCHEMAS_ATTRGROUP_MARKED) {
12953 attr = attr->next;
12954 continue;
12955 } else {
12956 /*
12957 * Mark as visited to avoid infinite recursion on
12958 * circular references not yet examined.
12959 */
12960 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
12961 marked = 1;
12962 }
12963 }
12964 if (gr->attributes != NULL)
12965 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
12966 /*
12967 * Unmark the visited group's attributes.
12968 */
12969 if (marked)
12970 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
12971 if (circ != NULL)
12972 return (circ);
12973 }
12974 attr = attr->next;
12975 }
12976 return (NULL);
12977}
12978
12979/**
12980 * xmlSchemaCheckSRCAttributeGroupCircular:
12981 * attrGr: the attribute group definition
12982 * @ctxt: the parser context
12983 * @name: the name
12984 *
12985 * Checks for circular references of attribute groups.
12986 */
12987static void
12988xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
12989 xmlSchemaParserCtxtPtr ctxt,
12990 const xmlChar * name ATTRIBUTE_UNUSED)
12991{
12992 /*
12993 * Schema Representation Constraint:
12994 * Attribute Group Definition Representation OK
12995 * 3 Circular group reference is disallowed outside <redefine>.
12996 * That is, unless this element information item's parent is
12997 * <redefine>, then among the [children], if any, there must
12998 * not be an <attributeGroup> with ref [attribute] which resolves
12999 * to the component corresponding to this <attributeGroup>. Indirect
13000 * circularity is also ruled out. That is, when QName resolution
13001 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13002 * any <attributeGroup>s with a ref [attribute] among the [children],
13003 * it must not be the case that a ·QName· is encountered at any depth
13004 * which resolves to the component corresponding to this <attributeGroup>.
13005 */
13006 /*
13007 * Only global components can be referenced.
13008 */
13009 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
13010 (attrGr->attributes == NULL))
13011 return;
13012 else {
13013 xmlSchemaAttributeGroupPtr circ;
13014
13015 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
13016 if (circ != NULL) {
13017 /*
13018 * TODO: Report the referenced attr group as QName.
13019 */
13020 xmlSchemaPCustomErr(ctxt,
13021 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13022 NULL, NULL, circ->node,
13023 "Circular reference to the attribute group '%s' "
13024 "defined", attrGr->name);
13025 /*
13026 * NOTE: We will cut the reference to avoid further
13027 * confusion of the processor.
13028 * BADSPEC: The spec should define how to process in this case.
13029 */
13030 circ->attributes = NULL;
13031 circ->refItem = NULL;
13032 }
13033 }
13034}
13035
13036/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013037 * xmlSchemaAttrGrpFixup:
13038 * @attrgrpDecl: the schema attribute definition
13039 * @ctxt: the schema parser context
13040 * @name: the attribute name
13041 *
13042 * Fixes finish doing the computations on the attributes definitions
13043 */
13044static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013045xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013046 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013047{
13048 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013049 name = attrgrp->name;
13050 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013051 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013052 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013053 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013054
Daniel Veillardc0826a72004-08-10 14:17:33 +000013055 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13056 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013057 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013058 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013059 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013060 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13061 "ref", attrgrp->ref, attrgrp->refNs,
13062 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013063 return;
13064 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013065 attrgrp->refItem = ref;
13066 /*
13067 * Check for self reference!
13068 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013069 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013070 attrgrp->attributes = ref->attributes;
13071 attrgrp->attributeWildcard = ref->attributeWildcard;
13072 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013073}
13074
13075/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013076 * xmlSchemaAttrCheckValConstr:
13077 * @item: an schema attribute declaration/use
13078 * @ctxt: a schema parser context
13079 * @name: the name of the attribute
13080 *
13081 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013082 *
13083 * Fixes finish doing the computations on the attributes definitions
13084 */
13085static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013086xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13087 xmlSchemaParserCtxtPtr ctxt,
13088 const xmlChar * name ATTRIBUTE_UNUSED)
13089{
13090
13091 /*
13092 * a-props-correct
13093 * Schema Component Constraint: Attribute Declaration Properties Correct
13094 *
13095 * 2 if there is a {value constraint}, the canonical lexical
13096 * representation of its value must be ·valid· with respect
13097 * to the {type definition} as defined in String Valid (§3.14.4).
13098 */
13099
13100 if (item->defValue != NULL) {
13101 int ret;
13102 xmlNodePtr node;
13103 xmlSchemaTypePtr type;
13104
13105 if (item->subtypes == NULL) {
13106 xmlSchemaPErr(ctxt, item->node,
13107 XML_SCHEMAP_INTERNAL,
13108 "Internal error: xmlSchemaCheckAttrValConstr, "
13109 "type is missing... skipping validation of "
13110 "value constraint", NULL, NULL);
13111 return;
13112 }
13113
13114 /*
13115 * TODO: Try to avoid creating a new context.
13116 * TODO: This all is not very performant.
13117 */
13118 type = item->subtypes;
13119 /*
13120 * Ensure there's validation context.
13121 */
13122 if (ctxt->vctxt == NULL) {
13123 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13124 xmlSchemaPErr(ctxt, item->node,
13125 XML_SCHEMAP_INTERNAL,
13126 "Internal error: xmlSchemaCheckAttrValConstr, "
13127 "creating a new validation context.\n",
13128 NULL, NULL);
13129 return;
13130 }
13131 }
13132
13133 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13134 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13135 else
13136 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13137 ctxt->vctxt->node = node;
13138 ctxt->vctxt->cur = NULL;
13139 /*
13140 * NOTE: This call does not check the content nodes,
13141 * since they are not available:
13142 * facet->node is just the node holding the facet
13143 * definition, *not* the attribute holding the *value*
13144 * of the facet.
13145 */
13146 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13147 item->defValue, 0, 1, 1, 0);
13148 if (ret == 0) {
13149 /*
13150 * Store the computed value.
13151 */
13152 item->defVal = ctxt->vctxt->value;
13153 ctxt->vctxt->value = NULL;
13154 } else if (ret > 0) {
13155 if (ctxt != NULL) {
13156 xmlSchemaPSimpleTypeErr(ctxt,
13157 XML_SCHEMAP_A_PROPS_CORRECT_2,
13158 NULL, NULL, node,
13159 type, NULL, item->defValue,
13160 NULL, NULL, NULL);
13161 }
13162 } else if (ret < 0) {
13163 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13164 NULL, NULL, node,
13165 "Internal error: xmlSchemaAttrCheckValConstr, "
13166 "failed to validate the value constraint of the "
13167 "attribute decl/use against the type '%s'",
13168 type->name);
13169 }
13170 }
13171}
13172
13173#if 0 /* Not used yet. */
13174static int
13175xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13176 xmlSchemaElementPtr edecl)
13177{
13178 /*
13179 * TODO: 1 The values of the properties of an element declaration must be as
13180 * described in the property tableau in The Element Declaration Schema
13181 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13182 */
13183 /*
13184 * 2 If there is a {value constraint}, the canonical lexical
13185 * representation of its value must be ·valid· with respect to the {type
13186 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13187 *
13188 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13189 */
13190 /*
13191 * 3 If there is a non-·absent· {substitution group affiliation},
13192 * then {scope} must be global.
13193 *
13194 * NOTE: This is done in xmlSchemaParseElement.
13195 * TODO: Move it to this layer here.
13196 */
13197 /*
13198 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13199 * of the element declaration must be validly derived from the {type
13200 * definition} of the {substitution group affiliation}, given the value
13201 * of the {substitution group exclusions} of the {substitution group
13202 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13203 * (if the {type definition} is complex) or as defined in
13204 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13205 * simple).
13206 */
13207 /*
13208 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13209 * is or is derived from ID then there must not be a {value constraint}.
13210 * Note: The use of ID as a type definition for elements goes beyond
13211 * XML 1.0, and should be avoided if backwards compatibility is desired
13212 */
13213 /*
13214 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13215 * be possible to return to an element declaration by repeatedly following
13216 * the {substitution group affiliation} property.
13217 */
13218}
13219#endif
13220
13221/**
13222 * xmlSchemaCheckElemValConstr:
13223 * @item: an schema element declaration/particle
13224 * @ctxt: a schema parser context
13225 * @name: the name of the attribute
13226 *
13227 * Validates the value constraints of an element declaration.
13228 *
13229 * Fixes finish doing the computations on the element declarations.
13230 */
13231static void
13232xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13233 xmlSchemaParserCtxtPtr ctxt,
13234 const xmlChar * name ATTRIBUTE_UNUSED)
13235{
13236 if (decl->value != NULL) {
13237 int ret;
13238 xmlNodePtr node = NULL;
13239 xmlSchemaTypePtr type;
13240
13241 /*
13242 * 2 If there is a {value constraint}, the canonical lexical
13243 * representation of its value must be ·valid· with respect to the {type
13244 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13245 */
13246 if (decl->subtypes == NULL) {
13247 xmlSchemaPErr(ctxt, decl->node,
13248 XML_SCHEMAP_INTERNAL,
13249 "Internal error: xmlSchemaCheckElemValConstr, "
13250 "type is missing... skipping validation of "
13251 "the value constraint", NULL, NULL);
13252 return;
13253 }
13254 /*
13255 * Ensure there's a validation context.
13256 */
13257 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13258 return;
13259
13260 type = decl->subtypes;
13261
13262 if (decl->node != NULL) {
13263 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13264 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13265 else
13266 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13267 }
13268 ctxt->vctxt->node = node;
13269 ctxt->vctxt->cur = NULL;
13270 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13271 node);
13272 if (ret == 0) {
13273 /*
13274 * Consume the computed value.
13275 */
13276 decl->defVal = ctxt->vctxt->value;
13277 ctxt->vctxt->value = NULL;
13278 } else if (ret < 0) {
13279 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13280 NULL, NULL, node,
13281 "Internal error: xmlSchemaElemCheckValConstr, "
13282 "failed to validate the value constraint of the "
13283 "element declaration '%s'",
13284 decl->name);
13285 }
13286 }
13287}
13288
13289/**
13290 * xmlSchemaAttrFixup:
13291 * @item: an schema attribute declaration/use.
13292 * @ctxt: a schema parser context
13293 * @name: the name of the attribute
13294 *
13295 * Fixes finish doing the computations on attribute declarations/uses.
13296 */
13297static void
13298xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13299 xmlSchemaParserCtxtPtr ctxt,
13300 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013301{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013302 /*
13303 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013304 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013305 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013306 /*
13307 * The simple type definition corresponding to the <simpleType> element
13308 * information item in the [children], if present, otherwise the simple
13309 * type definition ·resolved· to by the ·actual value· of the type
13310 * [attribute], if present, otherwise the ·simple ur-type definition·.
13311 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013312 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013313 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013314 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13315 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013316 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013317 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013318 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013319
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013320 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13321 item->typeNs);
13322 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013323 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013324 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013325 NULL, (xmlSchemaTypePtr) item, item->node,
13326 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013327 XML_SCHEMA_TYPE_SIMPLE, NULL);
13328 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013329 item->subtypes = type;
13330
13331 } else if (item->ref != NULL) {
13332 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013333
Daniel Veillardc0826a72004-08-10 14:17:33 +000013334 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013335 * We have an attribute use here; assign the referenced
13336 * attribute declaration.
13337 */
13338 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013339 * TODO: Evaluate, what errors could occur if the declaration is not
13340 * found. It might be possible that the "typefixup" might crash if
13341 * no ref declaration was found.
13342 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013343 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13344 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013345 xmlSchemaPResCompAttrErr(ctxt,
13346 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013347 NULL, (xmlSchemaTypePtr) item, item->node,
13348 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013349 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013350 return;
13351 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013352 item->refDecl = decl;
13353 xmlSchemaAttrFixup(decl, ctxt, NULL);
13354
13355 item->subtypes = decl->subtypes;
13356 /*
13357 * Attribute Use Correct
13358 * au-props-correct.2: If the {attribute declaration} has a fixed
13359 * {value constraint}, then if the attribute use itself has a
13360 * {value constraint}, it must also be fixed and its value must match
13361 * that of the {attribute declaration}'s {value constraint}.
13362 */
13363 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13364 (item->defValue != NULL)) {
13365 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13366 (!xmlStrEqual(item->defValue, decl->defValue))) {
13367 xmlSchemaPCustomErr(ctxt,
13368 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13369 NULL, NULL, item->node,
13370 "The value constraint must be fixed "
13371 "and match the referenced attribute "
13372 "declarations's value constraint '%s'",
13373 decl->defValue);
13374 }
13375 /*
13376 * FUTURE: One should change the values of the attr. use
13377 * if ever validation should be attempted even if the
13378 * schema itself was not fully valid.
13379 */
13380 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013381 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013382 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13383 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013384}
13385
13386/**
13387 * xmlSchemaParse:
13388 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013389 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013390 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013391 * XML Shema struture which can be used to validate instances.
13392 * *WARNING* this interface is highly subject to change
13393 *
13394 * Returns the internal XML Schema structure built from the resource or
13395 * NULL in case of error
13396 */
13397xmlSchemaPtr
13398xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13399{
13400 xmlSchemaPtr ret = NULL;
13401 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013402 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013403 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013404
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013405 /*
13406 * This one is used if the schema to be parsed was specified via
13407 * the API; i.e. not automatically by the validated instance document.
13408 */
13409
Daniel Veillard4255d502002-04-16 15:50:10 +000013410 xmlSchemaInitTypes();
13411
Daniel Veillard6045c902002-10-09 21:13:59 +000013412 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013413 return (NULL);
13414
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013415 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013416 ctxt->counter = 0;
13417 ctxt->container = NULL;
13418
13419 /*
13420 * First step is to parse the input document into an DOM/Infoset
13421 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013422 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013423 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13424 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013425 if (doc == NULL) {
13426 xmlSchemaPErr(ctxt, NULL,
13427 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013428 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013429 ctxt->URL, NULL);
13430 return (NULL);
13431 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013432 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013433 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13434 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013435 if (doc == NULL) {
13436 xmlSchemaPErr(ctxt, NULL,
13437 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013438 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013439 NULL, NULL);
13440 return (NULL);
13441 }
13442 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013443 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013444 } else if (ctxt->doc != NULL) {
13445 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013446 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013447 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013448 xmlSchemaPErr(ctxt, NULL,
13449 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013450 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013451 NULL, NULL);
13452 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013453 }
13454
13455 /*
13456 * Then extract the root and Schema parse it
13457 */
13458 root = xmlDocGetRootElement(doc);
13459 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013460 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13461 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013462 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013463 if (!preserve) {
13464 xmlFreeDoc(doc);
13465 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013466 return (NULL);
13467 }
13468
13469 /*
13470 * Remove all the blank text nodes
13471 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013472 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013473
13474 /*
13475 * Then do the parsing for good
13476 */
13477 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013478 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013479 if (!preserve) {
13480 xmlFreeDoc(doc);
13481 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013482 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013483 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013484 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013485 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013486 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013487 ctxt->ctxtType = NULL;
13488 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013489 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013490 * Then fixup all attributes declarations
13491 */
13492 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13493
13494 /*
13495 * Then fixup all attributes group declarations
13496 */
13497 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13498 ctxt);
13499
13500 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013501 * Check attribute groups for circular references.
13502 */
13503 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13504 xmlSchemaCheckAttributeGroupCircular, ctxt);
13505
13506 /*
13507 * Then fixup all model group definitions.
13508 */
13509 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013510
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013511 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013512 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013513 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013514 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013515
13516 /*
13517 * Then fix references of element declaration; apply constraints.
13518 */
13519 xmlHashScanFull(ret->elemDecl,
13520 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013521
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013522 /*
13523 * Check model groups defnitions for circular references.
13524 */
13525 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13526 xmlSchemaCheckGroupDefCircular, ctxt);
13527
Daniel Veillard4255d502002-04-16 15:50:10 +000013528 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013529 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013530 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013531 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013532 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013533
13534 /*
13535 * Then check the defaults part of the type like facets values
13536 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013537 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
13538 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013539
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013540 /*
13541 * Validate the value constraint of attribute declarations/uses.
13542 */
13543 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13544
13545 /*
13546 * Validate the value constraint of element declarations.
13547 */
13548 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13549
Daniel Veillardc0826a72004-08-10 14:17:33 +000013550
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013551 if (ctxt->nberrors != 0) {
13552 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013553 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013554 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013555 return (ret);
13556}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013557
Daniel Veillard4255d502002-04-16 15:50:10 +000013558/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013559 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013560 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013561 * @err: the error callback
13562 * @warn: the warning callback
13563 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013564 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013565 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013566 */
13567void
13568xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013569 xmlSchemaValidityErrorFunc err,
13570 xmlSchemaValidityWarningFunc warn, void *ctx)
13571{
Daniel Veillard4255d502002-04-16 15:50:10 +000013572 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013573 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013574 ctxt->error = err;
13575 ctxt->warning = warn;
13576 ctxt->userData = ctx;
13577}
13578
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013579/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013580 * xmlSchemaGetParserErrors:
13581 * @ctxt: a XMl-Schema parser context
13582 * @err: the error callback result
13583 * @warn: the warning callback result
13584 * @ctx: contextual data for the callbacks result
13585 *
13586 * Get the callback information used to handle errors for a parser context
13587 *
13588 * Returns -1 in case of failure, 0 otherwise
13589 */
13590int
13591xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13592 xmlSchemaValidityErrorFunc * err,
13593 xmlSchemaValidityWarningFunc * warn, void **ctx)
13594{
13595 if (ctxt == NULL)
13596 return(-1);
13597 if (err != NULL)
13598 *err = ctxt->error;
13599 if (warn != NULL)
13600 *warn = ctxt->warning;
13601 if (ctx != NULL)
13602 *ctx = ctxt->userData;
13603 return(0);
13604}
13605
13606/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013607 * xmlSchemaFacetTypeToString:
13608 * @type: the facet type
13609 *
13610 * Convert the xmlSchemaTypeType to a char string.
13611 *
13612 * Returns the char string representation of the facet type if the
13613 * type is a facet and an "Internal Error" string otherwise.
13614 */
13615static const char *
13616xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13617{
13618 switch (type) {
13619 case XML_SCHEMA_FACET_PATTERN:
13620 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013621 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013622 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013623 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013624 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013625 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013626 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013627 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013628 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013629 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013630 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013631 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013632 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013633 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013634 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013635 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013636 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013637 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013638 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013639 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013640 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013641 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013642 return ("fractionDigits");
13643 default:
13644 break;
13645 }
13646 return ("Internal Error");
13647}
13648
Daniel Veillardc0826a72004-08-10 14:17:33 +000013649
Daniel Veillardc0826a72004-08-10 14:17:33 +000013650
13651static int
13652xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13653{
13654 xmlSchemaTypePtr anc;
13655
13656 /*
13657 * The normalization type can be changed only for types which are derived
13658 * from xsd:string.
13659 */
13660 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013661 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013662 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013663 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
13664 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013665 else {
13666 /*
13667 * For all ·atomic· datatypes other than string (and types ·derived·
13668 * by ·restriction· from it) the value of whiteSpace is fixed to
13669 * collapse
13670 */
13671 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13672 }
13673 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13674 /*
13675 * For list types the facet "whiteSpace" is fixed to "collapse".
13676 */
13677 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13678 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13679 return (-1);
13680 } else if (type->facetSet != NULL) {
13681 xmlSchemaTypePtr anyST;
13682 xmlSchemaFacetLinkPtr lin;
13683
13684 /*
13685 * Atomic types.
13686 */
13687 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13688 anc = type->baseType;
13689 do {
13690 /*
13691 * For all ·atomic· datatypes other than string (and types ·derived·
13692 * by ·restriction· from it) the value of whiteSpace is fixed to
13693 * collapse
13694 */
13695 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13696 (anc->builtInType == XML_SCHEMAS_STRING)) {
13697
13698 lin = type->facetSet;
13699 do {
13700 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13701 if (lin->facet->whitespace ==
13702 XML_SCHEMAS_FACET_COLLAPSE) {
13703 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13704 } else if (lin->facet->whitespace ==
13705 XML_SCHEMAS_FACET_REPLACE) {
13706 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13707 } else
13708 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13709 break;
13710 }
13711 lin = lin->next;
13712 } while (lin != NULL);
13713 break;
13714 }
13715 anc = anc->baseType;
13716 } while (anc != anyST);
13717 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13718 }
13719 return (-1);
13720}
13721
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013722/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013723 * xmlSchemaValidateFacetsInternal:
13724 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013725 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013726 * @facets: the list of facets to check
13727 * @value: the lexical repr of the value to validate
13728 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013729 * @fireErrors: if 0, only internal errors will be fired;
13730 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013731 *
13732 * Check a value against all facet conditions
13733 *
13734 * Returns 0 if the element is schemas valid, a positive error code
13735 * number otherwise and -1 in case of internal or API error.
13736 */
13737static int
13738xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013739 xmlSchemaTypePtr type,
13740 const xmlChar * value,
13741 unsigned long length,
13742 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013743{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013744 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013745 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013746 xmlSchemaTypePtr biType; /* The build-in type. */
13747 xmlSchemaTypePtr tmpType;
13748 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013749 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013750 xmlSchemaFacetPtr facet;
13751 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013752
Daniel Veillardc0826a72004-08-10 14:17:33 +000013753#ifdef DEBUG_UNION_VALIDATION
13754 printf("Facets of type: '%s'\n", (const char *) type->name);
13755 printf(" fireErrors: %d\n", fireErrors);
13756#endif
13757
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013758 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013759 /*
13760 * NOTE: Do not jump away, if the facetSet of the given type is
13761 * empty: until now, "pattern" facets of the *base types* need to
13762 * be checked as well.
13763 */
13764 biType = type->baseType;
13765 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13766 biType = biType->baseType;
13767 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013768 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013769 "Internal error: xmlSchemaValidateFacetsInternal, "
13770 "the base type axis of the given type '%s' does not resolve to "
13771 "a built-in type.\n",
13772 type->name, NULL);
13773 return (-1);
13774 }
13775
13776 if (type->facetSet != NULL) {
13777 facetLink = type->facetSet;
13778 while (facetLink != NULL) {
13779 facet = facetLink->facet;
13780 /*
13781 * Skip the pattern "whiteSpace": it is used to
13782 * format the character content beforehand.
13783 */
13784 switch (facet->type) {
13785 case XML_SCHEMA_FACET_WHITESPACE:
13786 case XML_SCHEMA_FACET_PATTERN:
13787 case XML_SCHEMA_FACET_ENUMERATION:
13788 break;
13789 case XML_SCHEMA_FACET_LENGTH:
13790 case XML_SCHEMA_FACET_MINLENGTH:
13791 case XML_SCHEMA_FACET_MAXLENGTH:
13792 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13793 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13794 value, length, 0);
13795 len = length;
13796 } else
13797 ret = xmlSchemaValidateLengthFacet(biType, facet,
13798 value, ctxt->value, &len);
13799 break;
13800 default:
13801 ret = xmlSchemaValidateFacet(biType, facet, value,
13802 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013803 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013804 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013805 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013806 "Internal error: xmlSchemaValidateFacetsInternal, "
13807 "validating facet of type '%s'.\n",
13808 type->name, NULL);
13809 break;
13810 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013811 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013812 type, facet, NULL, NULL, NULL, NULL);
13813 }
13814
13815 facetLink = facetLink->next;
13816 }
13817 if (ret >= 0) {
13818 /*
13819 * Process enumerations.
13820 */
13821 retFacet = 0;
13822 facetLink = type->facetSet;
13823 while (facetLink != NULL) {
13824 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
13825 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13826 value, ctxt->value);
13827 if (retFacet <= 0)
13828 break;
13829 }
13830 facetLink = facetLink->next;
13831 }
13832 if (retFacet > 0) {
13833 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
13834 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013835 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013836 value, 0, type, NULL, NULL, NULL, NULL, NULL);
13837 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013838 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013839 "Internal error: xmlSchemaValidateFacetsInternal, "
13840 "validating facet of type '%s'.\n",
13841 BAD_CAST "enumeration", NULL);
13842 ret = -1;
13843 }
13844 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013845 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013846 if (ret >= 0) {
13847 /*
13848 * Process patters. Pattern facets are ORed at type level
13849 * and ANDed if derived. Walk the base type axis.
13850 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013851 tmpType = type;
13852 facet = NULL;
13853 do {
13854 retFacet = 0;
13855 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013856 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013857 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13858 continue;
13859 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13860 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013861 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013862 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013863 else if (retFacet < 0) {
13864 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13865 "Internal error: xmlSchemaValidateFacetsInternal, "
13866 "validating 'pattern' facet '%s' of type '%s'.\n",
13867 facetLink->facet->value, tmpType->name);
13868 ret = -1;
13869 break;
13870 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013871 /* Save the last non-validating facet. */
13872 facet = facetLink->facet;
13873 }
13874 if (retFacet != 0)
13875 break;
13876 tmpType = tmpType->baseType;
13877 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013878 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013879 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13880 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013881 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013882 NULL, NULL, NULL, NULL);
13883 }
13884 }
13885 }
13886
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013887 return (ret);
13888}
13889
Daniel Veillard4255d502002-04-16 15:50:10 +000013890/************************************************************************
13891 * *
13892 * Simple type validation *
13893 * *
13894 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013895
Daniel Veillard4255d502002-04-16 15:50:10 +000013896
13897/************************************************************************
13898 * *
13899 * DOM Validation code *
13900 * *
13901 ************************************************************************/
13902
Daniel Veillard4255d502002-04-16 15:50:10 +000013903static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013904 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013905 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013906static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013907 xmlSchemaTypePtr type,
13908 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000013909
Daniel Veillard3646d642004-06-02 19:19:14 +000013910
13911/**
13912 * xmlSchemaFreeAttrStates:
13913 * @state: a list of attribute states
13914 *
13915 * Free the given list of attribute states
13916 *
13917 */
13918static void
13919xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13920{
13921 xmlSchemaAttrStatePtr tmp;
13922 while (state != NULL) {
13923 tmp = state;
13924 state = state->next;
13925 xmlFree(tmp);
13926 }
13927}
13928
Daniel Veillard4255d502002-04-16 15:50:10 +000013929/**
13930 * xmlSchemaRegisterAttributes:
13931 * @ctxt: a schema validation context
13932 * @attrs: a list of attributes
13933 *
13934 * Register the list of attributes as the set to be validated on that element
13935 *
13936 * Returns -1 in case of error, 0 otherwise
13937 */
13938static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013939xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
13940{
Daniel Veillard3646d642004-06-02 19:19:14 +000013941 xmlSchemaAttrStatePtr tmp;
13942
13943 ctxt->attr = NULL;
13944 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013945 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013946 if ((attrs->ns != NULL) &&
13947 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
13948 attrs = attrs->next;
13949 continue;
13950 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013951 tmp = (xmlSchemaAttrStatePtr)
13952 xmlMalloc(sizeof(xmlSchemaAttrState));
13953 if (tmp == NULL) {
13954 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
13955 return (-1);
13956 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013957 tmp->attr = attrs;
13958 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
13959 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013960 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013961 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013962 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013963 else
13964 ctxt->attrTop->next = tmp;
13965 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013966 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013967 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013968 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000013969}
13970
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013971#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000013972/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013973 * xmlSchemaValidateCheckNodeList
13974 * @nodelist: the list of nodes
13975 *
13976 * Check the node list is only made of text nodes and entities pointing
13977 * to text nodes
13978 *
13979 * Returns 1 if true, 0 if false and -1 in case of error
13980 */
13981static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013982xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
13983{
Daniel Veillard4255d502002-04-16 15:50:10 +000013984 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013985 if (nodelist->type == XML_ENTITY_REF_NODE) {
13986 TODO /* implement recursion in the entity content */
13987 }
13988 if ((nodelist->type != XML_TEXT_NODE) &&
13989 (nodelist->type != XML_COMMENT_NODE) &&
13990 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000013991 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013992 return (0);
13993 }
13994 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013995 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013996 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013997}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013998#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013999
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014000static void
14001xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14002{
14003 int i, nbItems;
14004 xmlSchemaTypePtr item, *items;
14005
14006
14007 /*
14008 * During the Assemble of the schema ctxt->curItems has
14009 * been filled with the relevant new items. Fix those up.
14010 */
14011 nbItems = ctxt->assemble->nbItems;
14012 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14013
14014 for (i = 0; i < nbItems; i++) {
14015 item = items[i];
14016 switch (item->type) {
14017 case XML_SCHEMA_TYPE_ATTRIBUTE:
14018 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14019 break;
14020 case XML_SCHEMA_TYPE_ELEMENT:
14021 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14022 NULL, NULL, NULL);
14023 break;
14024 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14025 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14026 ctxt, NULL);
14027 break;
14028 case XML_SCHEMA_TYPE_GROUP:
14029 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14030 default:
14031 break;
14032 }
14033 }
14034 /*
14035 * Circularity checks.
14036 */
14037 for (i = 0; i < nbItems; i++) {
14038 item = items[i];
14039 switch (item->type) {
14040 case XML_SCHEMA_TYPE_GROUP:
14041 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14042 break;
14043 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14044 xmlSchemaCheckAttributeGroupCircular(
14045 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14046 break;
14047 default:
14048 break;
14049 }
14050 }
14051 /*
14052 * Fixup for all other item.
14053 * TODO: Hmm, not sure if starting from complex/simple types,
14054 * all subsequent items will be reached.
14055 */
14056 for (i = 0; i < nbItems; i++) {
14057 item = items[i];
14058 switch (item->type) {
14059 case XML_SCHEMA_TYPE_SIMPLE:
14060 case XML_SCHEMA_TYPE_COMPLEX:
14061 xmlSchemaTypeFixup(item, ctxt, NULL);
14062 break;
14063 default:
14064 break;
14065 }
14066 }
14067 /*
14068 * Check facet values. Note that facets are
14069 * hold by complex and simple type components only.
14070 */
14071 for (i = 0; i < nbItems; i++) {
14072 item = items[i];
14073 switch (item->type) {
14074 case XML_SCHEMA_TYPE_SIMPLE:
14075 case XML_SCHEMA_TYPE_COMPLEX:
14076 xmlSchemaCheckDefaults(item, ctxt, NULL);
14077 break;
14078 default:
14079 break;
14080 }
14081 }
14082 /*
14083 * Build the content model for complex types.
14084 */
14085 for (i = 0; i < nbItems; i++) {
14086 item = items[i];
14087 switch (item->type) {
14088 case XML_SCHEMA_TYPE_COMPLEX:
14089 xmlSchemaBuildContentModel(item, ctxt, NULL);
14090 break;
14091 default:
14092 break;
14093 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014094 }
14095 /*
14096 * Validate value contraint values.
14097 */
14098 for (i = 0; i < nbItems; i++) {
14099 item = items[i];
14100 switch (item->type) {
14101 case XML_SCHEMA_TYPE_ATTRIBUTE:
14102 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14103 break;
14104 case XML_SCHEMA_TYPE_ELEMENT:
14105 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14106 break;
14107 default:
14108 break;
14109 }
14110 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014111}
14112
14113/**
14114 * xmlSchemaAssembleByLocation:
14115 * @pctxt: a schema parser context
14116 * @vctxt: a schema validation context
14117 * @schema: the existing schema
14118 * @node: the node that fired the assembling
14119 * @nsName: the namespace name of the new schema
14120 * @location: the location of the schema
14121 *
14122 * Expands an existing schema by an additional schema.
14123 *
14124 * Returns 0 if the new schema is correct, a positive error code
14125 * number otherwise and -1 in case of an internal or API error.
14126 */
14127static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014128xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14129 xmlSchemaPtr schema,
14130 xmlNodePtr node,
14131 const xmlChar *nsName,
14132 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014133{
14134 const xmlChar *targetNs, *oldtns;
14135 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014136 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014137 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014138 xmlSchemaParserCtxtPtr pctxt;
14139
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014140 /*
14141 * This should be used:
14142 * 1. on <import>(s)
14143 * 2. if requested by the validated instance
14144 * 3. if requested via the API
14145 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014146 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014147 return (-1);
14148 /*
14149 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014150 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014151 if ((vctxt->pctxt == NULL) &&
14152 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14153 xmlSchemaVErr(vctxt, node,
14154 XML_SCHEMAV_INTERNAL,
14155 "Internal error: xmlSchemaAssembleByLocation, "
14156 "failed to create a temp. parser context.\n",
14157 NULL, NULL);
14158 return (-1);
14159 }
14160 pctxt = vctxt->pctxt;
14161 /*
14162 * Set the counter to produce unique names for anonymous items.
14163 */
14164 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014165 /*
14166 * Acquire the schema document.
14167 */
14168 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14169 nsName, location, &doc, &targetNs, 0);
14170 if (ret != 0) {
14171 if (doc != NULL)
14172 xmlFreeDoc(doc);
14173 } else if (doc != NULL) {
14174 docElem = xmlDocGetRootElement(doc);
14175 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014176 * Create new assemble info.
14177 */
14178 if (pctxt->assemble == NULL) {
14179 pctxt->assemble = xmlSchemaNewAssemble();
14180 if (pctxt->assemble == NULL) {
14181 xmlSchemaVErrMemory(vctxt,
14182 "Memory error: xmlSchemaAssembleByLocation, "
14183 "allocating assemble info", NULL);
14184 xmlFreeDoc(doc);
14185 return (-1);
14186 }
14187 }
14188 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014189 * Save and reset the context & schema.
14190 */
14191 oldflags = schema->flags;
14192 oldtns = schema->targetNamespace;
14193 olddoc = schema->doc;
14194
14195 xmlSchemaClearSchemaDefaults(schema);
14196 schema->targetNamespace = targetNs;
14197 /* schema->nbCurItems = 0; */
14198 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014199 pctxt->ctxtType = NULL;
14200 pctxt->parentItem = NULL;
14201
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014202 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14203 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014204 xmlSchemaPostSchemaAssembleFixup(pctxt);
14205 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014206 * Set the counter of items.
14207 */
14208 schema->counter = pctxt->counter;
14209 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014210 * Free the list of assembled components.
14211 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014212 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014213 /*
14214 * Restore the context & schema.
14215 */
14216 schema->flags = oldflags;
14217 schema->targetNamespace = oldtns;
14218 schema->doc = olddoc;
14219 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014220 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014221 return (ret);
14222}
14223
14224/**
14225 * xmlSchemaAssembleByXSIAttr:
14226 * @vctxt: a schema validation context
14227 * @xsiAttr: an xsi attribute
14228 * @noNamespace: whether a schema with no target namespace is exptected
14229 *
14230 * Expands an existing schema by an additional schema using
14231 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14232 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14233 * must be set to 1.
14234 *
14235 * Returns 0 if the new schema is correct, a positive error code
14236 * number otherwise and -1 in case of an internal or API error.
14237 */
14238static int
14239xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14240 xmlAttrPtr xsiAttr,
14241 int noNamespace)
14242{
14243 xmlChar *value;
14244 const xmlChar *cur, *end;
14245 const xmlChar *nsname = NULL, *location;
14246 int count = 0;
14247 int ret = 0;
14248
14249 if (xsiAttr == NULL) {
14250 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14251 NULL, NULL,
14252 "Internal error: xmlSchemaAssembleByXSIAttr, "
14253 "bad arguments", NULL);
14254 return (-1);
14255 }
14256 /*
14257 * Parse the value; we will assume an even number of values
14258 * to be given (this is how Xerces and XSV work).
14259 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014260 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014261 cur = value;
14262 do {
14263 if (noNamespace != 1) {
14264 /*
14265 * Get the namespace name.
14266 */
14267 while (IS_BLANK_CH(*cur))
14268 cur++;
14269 end = cur;
14270 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14271 end++;
14272 if (end == cur)
14273 break;
14274 count++;
14275 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14276 cur = end;
14277 }
14278 /*
14279 * Get the URI.
14280 */
14281 while (IS_BLANK_CH(*cur))
14282 cur++;
14283 end = cur;
14284 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14285 end++;
14286 if (end == cur)
14287 break;
14288 count++;
14289 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014290 cur = end;
14291 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014292 xsiAttr->parent, nsname, location);
14293 if (ret == -1) {
14294 xmlSchemaVCustomErr(vctxt,
14295 XML_SCHEMAV_INTERNAL,
14296 (xmlNodePtr) xsiAttr, NULL,
14297 "Internal error: xmlSchemaAssembleByXSIAttr, "
14298 "assembling schemata", NULL);
14299 if (value != NULL)
14300 xmlFree(value);
14301 return (-1);
14302 }
14303 } while (*cur != 0);
14304 if (value != NULL)
14305 xmlFree(value);
14306 return (ret);
14307}
14308
14309/**
14310 * xmlSchemaAssembleByXSIElem:
14311 * @vctxt: a schema validation context
14312 * @elem: an element node possibly holding xsi attributes
14313 * @noNamespace: whether a schema with no target namespace is exptected
14314 *
14315 * Assembles an existing schema by an additional schema using
14316 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14317 * of the given @elem.
14318 *
14319 * Returns 0 if the new schema is correct, a positive error code
14320 * number otherwise and -1 in case of an internal or API error.
14321 */
14322static int
14323xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14324 xmlNodePtr elem)
14325{
14326 int ret = 0, retNs = 0;
14327 xmlAttrPtr attr;
14328
14329 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14330 if (attr != NULL) {
14331 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14332 if (retNs == -1)
14333 return (-1);
14334 }
14335 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14336 if (attr != NULL) {
14337 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14338 if (ret == -1)
14339 return (-1);
14340 }
14341 if (retNs != 0)
14342 return (retNs);
14343 else
14344 return (ret);
14345}
14346
Daniel Veillard4255d502002-04-16 15:50:10 +000014347/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014348 * xmlSchemaValidateCallback:
14349 * @ctxt: a schema validation context
14350 * @name: the name of the element detected (might be NULL)
14351 * @type: the type
14352 *
14353 * A transition has been made in the automata associated to an element
14354 * content model
14355 */
14356static void
14357xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014358 const xmlChar * name ATTRIBUTE_UNUSED,
14359 xmlSchemaTypePtr type, xmlNodePtr node)
14360{
Daniel Veillard4255d502002-04-16 15:50:10 +000014361 xmlSchemaTypePtr oldtype = ctxt->type;
14362 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014363
Daniel Veillard4255d502002-04-16 15:50:10 +000014364#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014365 xmlGenericError(xmlGenericErrorContext,
14366 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014367 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014368#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014369 /*
14370 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14371 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014372 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014373 ctxt->node = node;
14374 ctxt->cur = node->children;
14375 /*
14376 * Assemble new schemata using xsi.
14377 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014378 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014379 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014380
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014381 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14382 if (ret == -1) {
14383 xmlSchemaVCustomErr(ctxt,
14384 XML_SCHEMAV_INTERNAL,
14385 ctxt->node, NULL,
14386 "Internal error: xmlSchemaValidateElement, "
14387 "assembling schema by xsi", NULL);
14388 return;
14389 }
14390 /*
14391 * NOTE: We won't react on schema parser errors here.
14392 * TODO: But a warning would be nice.
14393 */
14394 }
14395 switch (type->type) {
14396 case XML_SCHEMA_TYPE_ELEMENT: {
14397 /*
14398 * NOTE: The build of the content model
14399 * (xmlSchemaBuildAContentModel) ensures that the element
14400 * declaration (and not a reference to it) will be given.
14401 */
14402 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14403 /*
14404 * This is paranoid coding ;-)... it should not
14405 * happen here any more.
14406 */
14407 xmlSchemaVCustomErr(ctxt,
14408 XML_SCHEMAV_INTERNAL,
14409 node, NULL,
14410 "Internal error: xmlSchemaValidateCallback, "
14411 "element declaration 'reference' encountered, "
14412 "but an element declaration was expected",
14413 NULL);
14414 return;
14415 }
14416 xmlSchemaValidateElementByDeclaration(ctxt,
14417 (xmlSchemaElementPtr) type);
14418 break;
14419 }
14420 case XML_SCHEMA_TYPE_ANY:
14421 xmlSchemaValidateElementByWildcard(ctxt, type);
14422 break;
14423 default:
14424 break;
14425 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014426 ctxt->type = oldtype;
14427 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014428}
Daniel Veillard4255d502002-04-16 15:50:10 +000014429
Daniel Veillard01fa6152004-06-29 17:04:39 +000014430/**
14431 * xmlSchemaValidateSimpleTypeValue:
14432 * @ctxt: a schema validation context
14433 * @value: the value to be validated
14434 * @fireErrors: shall errors be reported?
14435 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014436 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014437 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014438 *
14439 * Validates a value by the given type (user derived or built-in).
14440 *
14441 * Returns 0 if the value is valid, a positive error code
14442 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014443 */
14444static int
14445xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014446 xmlSchemaTypePtr type,
14447 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014448 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014449 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014450 int normalize,
14451 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014452{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014453 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014454 int ret = 0;
14455 xmlChar *normValue = NULL;
14456 int wtsp;
14457
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014458 node = ctxt->node;
14459 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014460 wtsp = ctxt->valueWS;
14461 /*
14462 * Normalize the value.
14463 */
14464 if (normalize &&
14465 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14466 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14467
14468 if ((norm != -1) && (norm > ctxt->valueWS)) {
14469 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14470 normValue = xmlSchemaCollapseString(value);
14471 else
14472 normValue = xmlSchemaWhiteSpaceReplace(value);
14473 ctxt->valueWS = norm;
14474 if (normValue != NULL)
14475 value = (const xmlChar *) normValue;
14476 }
14477 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014478 /*
14479 * The nodes of a content must be checked only once,
14480 * this is not working since list types will fire this
14481 * multiple times.
14482 */
14483 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14484 xmlNodePtr cur = ctxt->cur;
14485
14486 do {
14487 switch (cur->type) {
14488 case XML_TEXT_NODE:
14489 case XML_CDATA_SECTION_NODE:
14490 case XML_PI_NODE:
14491 case XML_COMMENT_NODE:
14492 case XML_XINCLUDE_START:
14493 case XML_XINCLUDE_END:
14494 break;
14495 case XML_ENTITY_REF_NODE:
14496 case XML_ENTITY_NODE:
14497 /* TODO: Scour the entities for illegal nodes. */
14498 TODO break;
14499 case XML_ELEMENT_NODE: {
14500 /* NOTE: Changed to an internal error, since the
14501 * existence of an element node will be already checked in
14502 * xmlSchemaValidateElementBySimpleType and in
14503 * xmlSchemaValidateElementByComplexType.
14504 */
14505 xmlSchemaVCustomErr(ctxt,
14506 XML_SCHEMAV_INTERNAL,
14507 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14508 node, type,
14509 "Element '%s' found in simple type content",
14510 cur->name);
14511 return (XML_SCHEMAV_INTERNAL);
14512 }
14513 case XML_ATTRIBUTE_NODE:
14514 case XML_DOCUMENT_NODE:
14515 case XML_DOCUMENT_TYPE_NODE:
14516 case XML_DOCUMENT_FRAG_NODE:
14517 case XML_NOTATION_NODE:
14518 case XML_HTML_DOCUMENT_NODE:
14519 case XML_DTD_NODE:
14520 case XML_ELEMENT_DECL:
14521 case XML_ATTRIBUTE_DECL:
14522 case XML_ENTITY_DECL:
14523 case XML_NAMESPACE_DECL:
14524#ifdef LIBXML_DOCB_ENABLED
14525 case XML_DOCB_DOCUMENT_NODE:
14526#endif
14527 xmlSchemaVCustomErr(ctxt,
14528 XML_SCHEMAV_INTERNAL,
14529 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14530 node, NULL,
14531 "Node of unexpected type found in simple type content",
14532 NULL);
14533 return (XML_SCHEMAV_INTERNAL);
14534 }
14535 cur = cur->next;
14536 } while (cur != NULL);
14537 }
14538
William M. Brack2f2a6632004-08-20 23:09:47 +000014539 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14540 xmlSchemaTypePtr base, anyType;
14541
14542 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14543
14544 base = type->baseType;
14545 while ((base != NULL) &&
14546 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14547 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14548 (base != anyType)) {
14549 base = base->baseType;
14550 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014551 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014552 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014553 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014554 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14555 "validating complex type '%s'\n",
14556 type->name, NULL);
14557 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14558 /*
14559 * Check facets.
14560 */
14561 /*
14562 * This is somehow not nice, since if an error occurs
14563 * the reported type will be the complex type; the spec
14564 * wants a simple type to be created on the complex type
14565 * if it has a simple content. For now we have to live with
14566 * it.
14567 */
14568 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14569 value, 0, fireErrors);
14570 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014571 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014572 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14573 "validating facets of complex type '%s'\n",
14574 type->name, NULL);
14575 } else if (ret > 0) {
14576 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014577 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014578 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014579 }
14580 }
14581 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014582
14583 if (ctxt->value != NULL) {
14584 xmlSchemaFreeValue(ctxt->value);
14585 ctxt->value = NULL;
14586 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014587 /*
14588 * STREAM-READ-CHILDREN.
14589 */
14590 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014591 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014592 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14593 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14594 else
14595 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014596 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014597 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014598 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014599 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014600 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014601 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014602 }
14603 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14604 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14605 * a literal in the ·lexical space· of {base type definition}
14606 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014607 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014608 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014609 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014610 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014611 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014612 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014613 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014614 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014615 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014616 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014617 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014618 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014619 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014620 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014621 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14622 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014623 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014624 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014625 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014626 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014627 type->name, NULL);
14628 } else if (ret > 0) {
14629 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014630 /*
14631 Disabled, since the facet validation already reports errors.
14632 if (fireErrors)
14633 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14634 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014635 }
14636 }
14637 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14638
14639 xmlSchemaTypePtr tmpType;
14640 const xmlChar *cur, *end;
14641 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014642 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014643
14644 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14645 * of white space separated tokens, each of which ·match·es a literal
14646 * in the ·lexical space· of {item type definition}
14647 */
14648
Daniel Veillardc0826a72004-08-10 14:17:33 +000014649 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650 cur = value;
14651 do {
14652 while (IS_BLANK_CH(*cur))
14653 cur++;
14654 end = cur;
14655 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14656 end++;
14657 if (end == cur)
14658 break;
14659 tmp = xmlStrndup(cur, end - cur);
14660 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014661 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014662 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014663 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014664 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014665 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14666 "validating an item of list simple type '%s'\n",
14667 type->name, NULL);
14668 break;
14669 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014670 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014671 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014672 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014673 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014674 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014675 cur = end;
14676 } while (*cur != 0);
14677 /*
14678 * Check facets.
14679 */
14680 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014681 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014682 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014683 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014684 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014685 } else if ((ret == 0) && (applyFacets)) {
14686 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14687 value, len, fireErrors);
14688 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014689 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014690 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14691 "validating facets of list simple type '%s'\n",
14692 type->name, NULL);
14693 } else if (ret > 0) {
14694 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014695 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014696 Disabled, since the facet validation already reports errors.
14697 if (fireErrors)
14698 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014699 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014700 }
14701
Daniel Veillard01fa6152004-06-29 17:04:39 +000014702 }
14703 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14704 xmlSchemaTypeLinkPtr memberLink;
14705
14706 /*
14707 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14708 * not apply directly; however, the normalization behavior of ·union·
14709 * types is controlled by the value of whiteSpace on that one of the
14710 * ·memberTypes· against which the ·union· is successfully validated.
14711 *
14712 * This means that the value is normalized by the first validating
14713 * member type, then the facets of the union type are applied. This
14714 * needs changing of the value!
14715 */
14716
14717 /*
14718 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14719 * literal in the ·lexical space· of at least one member of
14720 * {member type definitions}
14721 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014722#ifdef DEBUG_UNION_VALIDATION
14723 printf("Union ST : '%s'\n", (const char *) type->name);
14724 printf(" fireErrors : %d\n", fireErrors);
14725 printf(" applyFacets: %d\n", applyFacets);
14726#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014727 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14728 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014729 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014730 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014731 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014732 type->name, NULL);
14733 ret = -1;
14734 }
14735 if (ret == 0) {
14736 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014737 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14738 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014739 if ((ret <= 0) || (ret == 0))
14740 break;
14741 memberLink = memberLink->next;
14742 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014743 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014744 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014745 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014746 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014747 type->name, NULL);
14748 } else if (ret > 0) {
14749 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014750 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014751 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014752 }
14753 }
14754 /*
14755 * Apply facets (pattern, enumeration).
14756 */
14757 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14758 int mws;
14759 /*
14760 * The normalization behavior of ·union· types is controlled by
14761 * the value of whiteSpace on that one of the ·memberTypes·
14762 * against which the ·union· is successfully validated.
14763 */
14764 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014765 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014766 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14767 "the value was already normalized for the union simple "
14768 "type '%s'.\n", type->name, NULL);
14769 }
14770 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14771 if (mws > ctxt->valueWS) {
14772 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14773 normValue = xmlSchemaCollapseString(value);
14774 else
14775 normValue = xmlSchemaWhiteSpaceReplace(value);
14776 if (normValue != NULL)
14777 value = (const xmlChar *) normValue;
14778 }
14779
14780 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14781 value, 0, fireErrors);
14782 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014783 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014784 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14785 "validating facets of union simple type '%s'\n",
14786 type->name, NULL);
14787 } else if (ret > 0) {
14788 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14789 /*
14790 if (fireErrors)
14791 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14792 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014793 }
14794 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014795 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014796 ctxt->valueWS = wtsp;
14797 if (normValue != NULL)
14798 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014799 return (ret);
14800}
14801
14802/**
14803 * xmlSchemaValidateSimpleTypeElement:
14804 * @ctxt: a schema validation context
14805 * @node: the element node to be validated.
14806 *
14807 * Validate the element against a simple type.
14808 *
14809 * Returns 0 if the element is valid, a positive error code
14810 * number otherwise and -1 in case of an internal or API error.
14811 */
14812static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014813xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014814 xmlSchemaTypePtr type,
14815 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014816{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014817 xmlSchemaTypePtr oldtype;
14818 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014819 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014820 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014821 int ret = 0, retval = 0;
14822
Daniel Veillard01fa6152004-06-29 17:04:39 +000014823 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014824 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
14825 "Internal error: xmlSchemaValidateElementBySimpleType, "
14826 "bad arguments", NULL);
14827 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014828 }
14829
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014830 oldtype = ctxt->type;
14831 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014832 /*
14833 * cvc-type: 3.1.2 The element information item must have no element
14834 * information item [children].
14835 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014836 /*
14837 * STREAM: Child nodes are processed.
14838 */
14839 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014840 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014841 /*
14842 * TODO: Entities, will they produce elements as well?
14843 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014844 if (cur->type == XML_ELEMENT_NODE) {
14845 xmlSchemaVCustomErr(ctxt,
14846 XML_SCHEMAV_CVC_TYPE_3_1_2,
14847 node, type,
14848 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014849 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014850 }
14851 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014852 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014853
Daniel Veillard01fa6152004-06-29 17:04:39 +000014854 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014855 * cvc-type 3.1.1:
14856 *
14857 * The attributes of must be empty, excepting those whose namespace name
14858 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
14859 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014860 */
14861 /*
14862 * STREAM: Attribute nodes are processed.
14863 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014864 attr = node->properties;
14865 while (attr != NULL) {
14866 if ((attr->ns == NULL) ||
14867 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
14868 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
14869 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
14870 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
14871 (!xmlStrEqual
14872 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014873 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014874 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
14875 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014876 }
14877 attr = attr->next;
14878 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014879 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014880 * This will skip validation if the type is 'anySimpleType' and
14881 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014882 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014883 if ((valSimpleContent == 1) &&
14884 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14885 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014886 xmlChar *value;
14887
14888 value = xmlNodeGetContent(node);
14889 /*
14890 * NOTE: This call will not check the content nodes, since
14891 * this should be checked here already.
14892 */
14893 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14894 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014895 if (value != NULL)
14896 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014897 if (retval != 0)
14898 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014899 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014900 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014901 return (ret);
14902}
Daniel Veillard4255d502002-04-16 15:50:10 +000014903
14904/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014905 * xmlSchemaValQNameAcquire:
14906 * @value: the lexical represantation of the QName value
14907 * @node: the node to search for the corresponding namespace declaration
14908 * @nsName: the resulting namespace name if found
14909 *
14910 * Checks that a value conforms to the lexical space of the type QName;
14911 * if valid, the corresponding namespace name is searched and retured
14912 * as a copy in @nsName. The local name is returned in @localName as
14913 * a copy.
14914 *
14915 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14916 * namespace declaration was found in scope; -1 in case of an internal or
14917 * API error.
14918 */
14919static int
14920xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14921 xmlChar **nsName, xmlChar **localName)
14922{
14923 int ret;
14924 xmlChar *local = NULL;
14925
14926 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14927 return (-1);
14928 *nsName = NULL;
14929 *localName = NULL;
14930 ret = xmlValidateQName(value, 1);
14931 if (ret == 0) {
14932 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014933 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014934
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014935 /*
14936 * NOTE: xmlSplitQName2 will return a duplicated
14937 * string.
14938 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014939 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014940 if (local == NULL)
14941 local = xmlStrdup(value);
14942 ns = xmlSearchNs(node->doc, node, prefix);
14943 /*
14944 * A namespace need not to be found if the prefix is NULL.
14945 */
14946 if (ns != NULL) {
14947 /*
14948 * TODO: Is it necessary to duplicate the URI here?
14949 */
14950 *nsName = xmlStrdup(ns->href);
14951 } else if (prefix != NULL) {
14952 xmlFree(prefix);
14953 if (local != NULL)
14954 xmlFree(local);
14955 return (2);
14956 }
14957 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014958 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014959 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014960 } else
14961 return (1);
14962 return (ret);
14963}
14964
14965/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014966 * xmlSchemaHasElemContent:
14967 * @node: the node
14968 *
14969 * Scours the content of the given node for element
14970 * nodes.
14971 *
14972 * Returns 1 if an element node is found,
14973 * 0 otherwise.
14974 */
14975static int
14976xmlSchemaHasElemContent(xmlNodePtr node)
14977{
14978 if (node == NULL)
14979 return (0);
14980 node = node->children;
14981 while (node != NULL) {
14982 if (node->type == XML_ELEMENT_NODE)
14983 return (1);
14984 node = node->next;
14985 }
14986 return (0);
14987}
14988/**
14989 * xmlSchemaHasElemOrCharContent:
14990 * @node: the node
14991 *
14992 * Scours the content of the given node for element
14993 * and character nodes.
14994 *
14995 * Returns 1 if an element or character node is found,
14996 * 0 otherwise.
14997 */
14998static int
14999xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15000{
15001 if (node == NULL)
15002 return (0);
15003 node = node->children;
15004 while (node != NULL) {
15005 switch (node->type) {
15006 case XML_ELEMENT_NODE:
15007 /*
15008 * TODO: Ask Daniel if these are all character nodes.
15009 */
15010 case XML_TEXT_NODE:
15011 case XML_CDATA_SECTION_NODE:
15012 /*
15013 * TODO: How XML_ENTITY_NODEs evaluated?
15014 */
15015 case XML_ENTITY_REF_NODE:
15016 case XML_ENTITY_NODE:
15017 return (1);
15018 break;
15019 default:
15020 break;
15021 }
15022 node = node->next;
15023 }
15024 return (0);
15025}
15026
15027
15028/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015029 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015030 * @ctxt: a schema validation context
15031 * @node: the top node.
15032 *
15033 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015034 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015035 *
15036 * Returns 0 if the element is schemas valid, a positive error code
15037 * number otherwise and -1 in case of internal or API error.
15038 */
15039static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015040xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15041 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015042{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015043 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015044 int ret = 0;
15045 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015046 xmlAttrPtr attr;
15047 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015048 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015049
15050 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015051 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15052 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015053 * Note that @elemDecl will be the declaration and never the
15054 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015055 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015056
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015057 if (ctxt == NULL) {
15058 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15059 "Internal error: xmlSchemaValidateElementByDeclaration, "
15060 "bad arguments.\n",
15061 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015062 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015063 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015064
15065 elem = ctxt->node;
15066
15067 /*
15068 * cvc-elt (3.3.4) : 1
15069 */
15070 if (elemDecl == NULL) {
15071 xmlSchemaVCustomErr(ctxt,
15072 XML_SCHEMAV_CVC_ELT_1,
15073 elem, NULL,
15074 "No matching declaration available", NULL);
15075 return (ctxt->err);
15076 }
15077 /*
15078 * cvc-elt (3.3.4) : 2
15079 */
15080 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15081 xmlSchemaVCustomErr(ctxt,
15082 XML_SCHEMAV_CVC_ELT_2,
15083 elem, NULL,
15084 "The element declaration is abstract", NULL);
15085 return (ctxt->err);
15086 }
15087
15088 /*
15089 * cvc-elt (3.3.4) : 3
15090 * Handle 'xsi:nil'.
15091 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015092
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015093 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015094 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015095 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15096 ctxt->node = (xmlNodePtr) attr;
15097 ctxt->cur = attr->children;
15098 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15099 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15100 BAD_CAST attrValue, 1, 1, 1, 1);
15101 ctxt->node = elem;
15102 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15103 if (ret < 0) {
15104 xmlSchemaVCustomErr(ctxt,
15105 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015106 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015107 "Internal error: xmlSchemaValidateElementByDeclaration, "
15108 "validating the attribute 'xsi:nil'", NULL);
15109 if (attrValue != NULL)
15110 xmlFree(attrValue);
15111 return (-1);
15112 }
15113 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015114 /*
15115 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015116 */
15117 xmlSchemaVCustomErr(ctxt,
15118 XML_SCHEMAV_CVC_ELT_3_1,
15119 elem, NULL,
15120 "The element is not 'nillable'", NULL);
15121 } else {
15122 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015123 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015124 ret = 0;
15125 /*
15126 * cvc-elt (3.3.4) : 3.2.1
15127 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015128 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15129 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015130 xmlSchemaVCustomErr(ctxt,
15131 XML_SCHEMAV_CVC_ELT_3_2_1,
15132 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015133 elem, (xmlSchemaTypePtr) elemDecl,
15134 "The 'nilled' element must have no character or "
15135 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015136 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15137 }
15138 /*
15139 * cvc-elt (3.3.4) : 3.2.2
15140 */
15141 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15142 (elemDecl->value != NULL)) {
15143 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15144 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015145 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015146 "There is a fixed value constraint defined for "
15147 "the 'nilled' element", NULL);
15148 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15149 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015150 if (ret == 0)
15151 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015152 }
15153 }
15154 if (attrValue != NULL)
15155 xmlFree(attrValue);
15156 }
15157
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015158
15159 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015160 /*
15161 * cvc-elt (3.3.4) : 4
15162 * Handle 'xsi:type'.
15163 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015164
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015165 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15166 if (attr != NULL) {
15167 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015168
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015169 /*
15170 * TODO: We should report a *warning* that the type was overriden
15171 * by the instance.
15172 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015173
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015174 /*
15175 * cvc-elt (3.3.4) : 4.1
15176 */
15177 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15178 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15179 &nsName, &local);
15180 if (ret < 0) {
15181 xmlSchemaVCustomErr(ctxt,
15182 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015183 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015184 "Internal error: xmlSchemaValidateElementByDeclaration, "
15185 "validating the attribute 'xsi:type'", NULL);;
15186 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015187 FREE_AND_NULL(nsName)
15188 FREE_AND_NULL(local)
15189 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015190 } else if (ret == 1) {
15191 xmlSchemaVSimpleTypeErr(ctxt,
15192 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15193 (xmlNodePtr) attr, attrValue,
15194 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15195 } else if (ret == 2) {
15196 xmlSchemaVCustomErr(ctxt,
15197 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15198 (xmlNodePtr) attr,
15199 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15200 "The QName value '%s' has no "
15201 "corresponding namespace declaration in scope",
15202 attrValue);
15203 } else {
15204 /*
15205 * cvc-elt (3.3.4) : 4.2
15206 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015207 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15208 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015209 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015210
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015211 xmlSchemaVCustomErr(ctxt,
15212 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015213 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015214 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15215 "The value %s does not resolve to a type "
15216 "definition",
15217 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15218 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015219 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015220 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015221 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015222 */
15223 }
15224 }
15225 FREE_AND_NULL(attrValue)
15226 FREE_AND_NULL(nsName)
15227 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015228 }
15229 /* TODO: Change the handling of missing types according to
15230 * the spec.
15231 */
15232 if (actualType == NULL) {
15233 xmlSchemaVComplexTypeErr(ctxt,
15234 XML_SCHEMAV_CVC_TYPE_1,
15235 elem, (xmlSchemaTypePtr) elemDecl,
15236 "The type definition is absent");
15237 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015238 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015239
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015240 /*
15241 * TODO: Since this should be already checked by the content model automaton,
15242 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15243 * has been changed to XML_SCHEMAV_INTERNAL.
15244 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015245 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015246 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015247 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015248 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015249 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015250 "Element %s: missing child %s\n",
15251 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015252 }
15253 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015254 }
15255 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015256 /*
15257 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015258 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015259 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015260 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015261 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015262 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015263 "Element %s: missing child %s found %s\n",
15264 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015265 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015266 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015267 */
15268 if (elemHasContent == -1)
15269 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15270 /*
15271 * cvc-elt (3.3.4) : 5
15272 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015273 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015274 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015275 * cvc-elt (3.3.4) : 5.1
15276 * If the declaration has a {value constraint},
15277 * the item has neither element nor character [children] and
15278 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015279 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015280 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15281 /*
15282 * cvc-elt (3.3.4) : 5.1.1
15283 * If the ·actual type definition· is a ·local type definition·
15284 * then the canonical lexical representation of the {value constraint}
15285 * value must be a valid default for the ·actual type definition· as
15286 * defined in Element Default Valid (Immediate) (§3.3.6).
15287 */
15288 /*
15289 * NOTE: 'local' above means types aquired by xsi:type.
15290 */
15291 ret = 0;
15292 if (actualType != elemDecl->subtypes) {
15293 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15294 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15295 elemDecl->value, NULL);
15296 if (ret < 0) {
15297 xmlSchemaVCustomErr(ctxt,
15298 XML_SCHEMAV_INTERNAL,
15299 elem, actualType,
15300 "Internal error: xmlSchemaValidateElementByDeclaration, "
15301 "validating a default value", NULL);
15302 return (-1);
15303 }
15304 }
15305 /*
15306 * cvc-elt (3.3.4) : 5.1.2
15307 * The element information item with the canonical lexical
15308 * representation of the {value constraint} value used as its
15309 * ·normalized value· must be ·valid· with respect to the
15310 * ·actual type definition· as defined by Element Locally Valid (Type)
15311 * (§3.3.4).
15312 */
15313 /*
15314 * Disable validation of the simple content, since it was already
15315 * done above.
15316 */
15317 if (ret == 0) {
15318 if (actualType != elemDecl->subtypes)
15319 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15320 else
15321 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15322 ctxt->node = elem;
15323 if (ret < 0) {
15324 xmlSchemaVCustomErr(ctxt,
15325 XML_SCHEMAV_INTERNAL,
15326 elem, actualType,
15327 "Internal error: xmlSchemaValidateElementByDeclaration, "
15328 "validating against the type", NULL);
15329 return (-1);
15330 }
15331 /*
15332 * PSVI: Create a text node on the instance element.
15333 */
15334 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15335 xmlNodePtr textChild;
15336
15337 textChild = xmlNewText(elemDecl->value);
15338 if (textChild == NULL) {
15339 xmlSchemaVCustomErr(ctxt,
15340 XML_SCHEMAV_INTERNAL,
15341 elem, actualType,
15342 "Internal error: xmlSchemaValidateElementByDeclaration, "
15343 "could not create a default text node for the instance",
15344 NULL);
15345 } else
15346 xmlAddChild(elem, textChild);
15347 }
15348 }
15349
15350 } else {
15351 /*
15352 * 5.2.1 The element information item must be ·valid· with respect
15353 * to the ·actual type definition· as defined by Element Locally
15354 * Valid (Type) (§3.3.4).
15355 */
15356 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15357 ctxt->node = elem;
15358 if (ret < 0) {
15359 xmlSchemaVCustomErr(ctxt,
15360 XML_SCHEMAV_INTERNAL,
15361 elem, actualType,
15362 "Internal error: xmlSchemaValidateElementByDeclaration, "
15363 "validating a default value", NULL);
15364 return (-1);
15365 }
15366 /*
15367 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15368 * not applied, all of the following must be true:
15369 */
15370
15371 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15372 /*
15373 * 5.2.2.1 The element information item must have no element
15374 * information item [children].
15375 *
15376 * TODO REDUNDANT: If the actual type exists, the above call to
15377 * xmlSchemaValidateElementByType will already check for element
15378 * nodes.
15379 */
15380 if (xmlSchemaHasElemContent(elem)) {
15381 xmlSchemaVCustomErr(ctxt,
15382 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15383 elem, (xmlSchemaTypePtr) elemDecl,
15384 "Elements in the content are not allowed if it is "
15385 "constrained by a fixed value", NULL);
15386 } else {
15387 /*
15388 * 5.2.2.2 The appropriate case among the following must
15389 * be true:
15390 */
15391
15392 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15393 xmlChar *value;
15394 /*
15395 * 5.2.2.2.1 If the {content type} of the ·actual type
15396 * definition· is mixed, then the *initial value* of the
15397 * item must match the canonical lexical representation
15398 * of the {value constraint} value.
15399 *
15400 * ... the *initial value* of an element information
15401 * item is the string composed of, in order, the
15402 * [character code] of each character information item in
15403 * the [children] of that element information item.
15404 */
15405 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15406 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15407 /*
15408 * TODO: Report invalid & expected values as well.
15409 * TODO: Implement the cononical stuff.
15410 */
15411 xmlSchemaVCustomErr(ctxt,
15412 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15413 elem, (xmlSchemaTypePtr) elemDecl,
15414 "The value does not match the cononical "
15415 "lexical representation of the fixed constraint",
15416 NULL);
15417 }
15418 if (value != NULL)
15419 xmlFree(value);
15420 } else if ((actualType->contentType ==
15421 XML_SCHEMA_CONTENT_SIMPLE) ||
15422 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15423 xmlChar *value;
15424
15425 /*
15426 * 5.2.2.2.2 If the {content type} of the ·actual type
15427 * definition· is a simple type definition, then the
15428 * *actual value* of the item must match the canonical
15429 * lexical representation of the {value constraint} value.
15430 */
15431 /*
15432 * TODO: *actual value* is the normalized value, impl. this.
15433 * TODO: Report invalid & expected values as well.
15434 * TODO: Implement the cononical stuff.
15435 *
15436 */
15437 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15438 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15439 xmlSchemaVCustomErr(ctxt,
15440 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15441 elem, (xmlSchemaTypePtr) elemDecl,
15442 "The normalized value does not match the cononical "
15443 "lexical representation of the fixed constraint",
15444 NULL);
15445 }
15446 if (value != NULL)
15447 xmlFree(value);
15448
15449 }
15450 /*
15451 * TODO: What if the content type is not 'mixed' or simple?
15452 */
15453
15454 }
15455
15456 }
15457 }
15458
15459 /*
15460 * TODO: 6 The element information item must be ·valid· with respect to each of
15461 * the {identity-constraint definitions} as per Identity-constraint
15462 * Satisfied (§3.11.4).
15463 */
15464
15465 /*
15466 * TODO: 7 If the element information item is the ·validation root·, it must be
15467 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15468 */
15469
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015470 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015471}
15472
Daniel Veillard4255d502002-04-16 15:50:10 +000015473/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015474 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015475 * @ctxt: a schema validation context
15476 * @node: the top node.
15477 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015478 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15479 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015480 *
15481 * Returns 0 if the element is valid, a positive error code
15482 * number otherwise and -1 in case of an internal error.
15483 */
15484static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015485xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15486 xmlSchemaWildcardPtr wild,
15487 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015488{
15489 const xmlChar *uri;
15490 int ret = 0;
15491 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015492
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015493 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015494 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15495 if (ret == -1) {
15496 xmlSchemaVCustomErr(ctxt,
15497 XML_SCHEMAV_INTERNAL,
15498 ctxt->node, NULL,
15499 "Internal error: xmlSchemaValidateElement, "
15500 "assembling schema by xsi", NULL);
15501 return (-1);
15502 }
15503 /*
15504 * NOTE: We won't react on schema parser errors here.
15505 * TODO: But a warning would be nice.
15506 */
15507 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015508 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15509 xmlSchemaElementPtr decl = NULL;
15510
15511 if (node->ns != NULL)
15512 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15513 node->name, node->ns->href, NULL);
15514 else
15515 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15516 if (decl != NULL) {
15517 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015518 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015519 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015520 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015521 "Internal error: xmlSchemaValidateAnyInternal, "
15522 "validating an element in the context of a wildcard.",
15523 NULL, NULL);
15524 } else if (ret > 0)
15525 return (ret);
15526 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15527 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015528 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015529 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015530 return (ctxt->err);
15531 }
15532 }
15533 if (node->children != NULL) {
15534 child = node->children;
15535 do {
15536 if (child->type == XML_ELEMENT_NODE) {
15537 if (child->ns != NULL)
15538 uri = child->ns->href;
15539 else
15540 uri = NULL;
15541 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015542 /* TODO: error code. */
15543 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015544 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015545 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015546 return (ctxt->err);
15547 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015548 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15549 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015550 if (ret != 0)
15551 return (ret);
15552 }
15553 child = child->next;
15554 } while (child != NULL);
15555 }
15556 return (0);
15557}
15558
15559/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015560 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015561 * @ctxt: a schema validation context
15562 *
15563 * Returns 0 if the element is valid, a positive error code
15564 * number otherwise and -1 in case of an internal or API error.
15565 */
15566static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015567xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15568 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015569{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015570 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15571 (ctxt->node == NULL)) {
15572 xmlSchemaVCustomErr(ctxt,
15573 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15574 "Internal error: xmlSchemaValidateElementByWildcard, "
15575 "bad arguments", NULL);
15576 return (-1);
15577 }
15578 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15579 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015580}
15581
15582/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015583 * xmlSchemaValidateAnyTypeContent:
15584 * @ctxt: a schema validation context
15585 * @node: the current element
15586 *
15587 * This one validates the content of an element of the type
15588 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15589 * thus elements in the subtree will be validated, if a corresponding
15590 * declaration in the schema exists.
15591 *
15592 * Returns 0 if the element and its subtree is valid, a positive error code
15593 * otherwise and -1 in case of an internal or API error.
15594 */
15595static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015596xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15597 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015598{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015599 xmlSchemaTypePtr oldtype;
15600 xmlNodePtr top, cur;
15601 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015602 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015603
15604 if ((type == NULL) || (ctxt->node == NULL))
15605 return (-1);
15606
15607 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015608 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015609
15610 oldtype = ctxt->type;
15611 top = ctxt->node;
15612 /*
15613 * STREAM: Child nodes are processed.
15614 */
15615 cur = ctxt->node->children;
15616 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015617 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015618 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015619 /*
15620 * The process contents of the wildcard is "lax", thus
15621 * we need to validate the element if a declaration
15622 * exists.
15623 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015624 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015625 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015626 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015627 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015628 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015629 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015630 ctxt->node = cur;
15631 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15632 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015633 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015634 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015635 "Internal error: xmlSchemaValidateAnyTypeContent, "
15636 "validating an element in the context of a wildcard.",
15637 NULL, NULL);
15638 return (ret);
15639 } else if (ret > 0)
15640 return (ret);
15641 skipContent = 1;
15642 }
15643 }
15644 /*
15645 * Browse the full subtree, deep first.
15646 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015647 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015648 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015649 cur = cur->children;
15650 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015651 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015652 cur = cur->next;
15653 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015654 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015655 while (cur != top) {
15656 if (cur->parent != NULL)
15657 cur = cur->parent;
15658 if ((cur != top) && (cur->next != NULL)) {
15659 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015660 break;
15661 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015662 if (cur->parent == NULL) {
15663 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015664 break;
15665 }
15666 }
15667 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015668 if (cur == top)
15669 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015670 } else
15671 break;
15672 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015673 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015674 return (0);
15675}
15676
15677/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015678 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015679 * @ctxt: a schema validation context
15680 * @node: the top node.
15681 *
15682 * Validate the content of an element expected to be a complex type type
15683 * xmlschema-1.html#cvc-complex-type
15684 * Validation Rule: Element Locally Valid (Complex Type)
15685 *
15686 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015687 * number otherwise and -1 in case of internal or API error.
15688 * Note on reported errors: Although it might be nice to report
15689 * the name of the simple/complex type, used to validate the content
15690 * of a node, it is quite unnecessary: for global defined types
15691 * the local name of the element is equal to the NCName of the type,
15692 * for local defined types it makes no sense to output the internal
15693 * computed name of the type. TODO: Instead, one should attach the
15694 * struct of the type involved to the error handler - this allows
15695 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015696 */
15697static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015698xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015699 xmlSchemaTypePtr type,
15700 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015701{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015702 xmlSchemaTypePtr oldtype;
15703 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015704 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015705 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015706 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015707
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015708 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15709 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015710
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015711 oldtype = ctxt->type;
15712 ctxt->type = type;
15713 elem = ctxt->node;
15714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015715 /*
15716 * Verify the attributes
15717 */
15718 /*
15719 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015720 */
15721 /* NOTE: removed, since a check for abstract is
15722 * done in the cvc-type constraint.
15723 *
15724 *
15725 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15726 * xmlSchemaVComplexTypeErr(ctxt,
15727 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15728 * elem, type,
15729 * "The type definition is abstract");
15730 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15731 *}
15732 */
15733
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015734 attrs = ctxt->attr;
15735 attrTop = ctxt->attrTop;
15736 /*
15737 * STREAM: Attribute nodes are processed.
15738 */
15739 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15740 xmlSchemaValidateAttributes(ctxt, elem, type);
15741 if (ctxt->attr != NULL)
15742 xmlSchemaFreeAttributeStates(ctxt->attr);
15743 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015744 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015745
15746 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015747 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015748 * model was defined. Somehow ->contModel is always not NULL
15749 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015750 * TODO: Check if the obove still occurs.
15751 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015752 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015753 case XML_SCHEMA_CONTENT_EMPTY: {
15754 /*
15755 * 1 If the {content type} is empty, then the element information
15756 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015757 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015758 /*
15759 * TODO: Is the entity stuff correct?
15760 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015761 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015762 xmlSchemaVComplexTypeErr(ctxt,
15763 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015764 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015765 "Character or element content is not allowed, "
15766 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015767 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015768 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015769 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015770 case XML_SCHEMA_CONTENT_MIXED:
15771 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015772 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015773 /*
15774 * The type has 'anyType' as its base and no content model
15775 * is defined -> use 'anyType' as the type to validate
15776 * against.
15777 */
15778 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15779 /* TODO: Handle -1. */
15780 break;
15781 }
15782 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015783 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015784 {
15785 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015786
15787 /*
15788 * Content model check initialization.
15789 */
15790 if (type->contModel != NULL) {
15791 oldregexp = ctxt->regexp;
15792 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15793 (xmlRegExecCallbacks)
15794 xmlSchemaValidateCallback, ctxt);
15795#ifdef DEBUG_AUTOMATA
15796 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15797#endif
15798 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015799 /*
15800 * STREAM: Children are processed.
15801 */
15802 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015803 while (child != NULL) {
15804 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015805 if (child->ns != NULL)
15806 nsUri = child->ns->href;
15807 else
15808 nsUri = NULL;
15809 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015810 child->name, nsUri, child);
15811 /*
15812 * URGENT TODO: Could we anchor an error report
15813 * here to notify of invalid elements?
15814 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015815#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000015816 if (ret < 0)
15817 xmlGenericError(xmlGenericErrorContext,
15818 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000015819 else
15820 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015821 " --> %s\n", child->name);
15822#endif
15823 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
15824 /*
15825 * TODO: Ask Daniel if this are all character nodes.
15826 */
15827 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
15828 (child->type == XML_ENTITY_NODE) ||
15829 (child->type == XML_ENTITY_REF_NODE) ||
15830 (child->type == XML_CDATA_SECTION_NODE))) {
15831 /*
15832 * 2.3 If the {content type} is element-only, then the
15833 * element information item has no character information
15834 * item [children] other than those whose [character
15835 * code] is defined as a white space in [XML 1.0 (Second
15836 * Edition)].
15837 */
William M. Brack2f2a6632004-08-20 23:09:47 +000015838 xmlSchemaVComplexTypeErr(ctxt,
15839 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015840 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015841 "Character content is not allowed, "
15842 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015843 break;
15844 }
15845 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015846 }
15847 /*
15848 * Content model check finalization.
15849 */
15850 if (type->contModel != NULL) {
15851 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
15852#ifdef DEBUG_AUTOMATA
15853 xmlGenericError(xmlGenericErrorContext,
15854 "====> %s : %d\n", elem->name, ret);
15855#endif
15856 if (ret == 0) {
15857 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15858 elem, type, "The element content is not valid", NULL);
15859 } else if (ret < 0) {
15860 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15861 elem, type, "The element content is not valid", NULL);
15862#ifdef DEBUG_CONTENT
15863 } else {
15864 xmlGenericError(xmlGenericErrorContext,
15865 "Element %s content check succeeded\n",
15866 elem->name);
15867
15868#endif
15869 }
15870 xmlRegFreeExecCtxt(ctxt->regexp);
15871 ctxt->regexp = oldregexp;
15872 }
15873 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015874 break;
15875 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015876 case XML_SCHEMA_CONTENT_BASIC:
15877 /*
15878 * If the simple content was already validated
15879 * (e.g. a default value), the content need not
15880 * to be validated again.
15881 */
15882 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015883 xmlChar *value = NULL;
15884 /*
15885 * We hit a complexType with a simpleContent resolving
15886 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000015887 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015888 /*
15889 * 2.2 If the {content type} is a simple type definition,
15890 * then the element information item has no element
15891 * information item [children], and the ·normalized value·
15892 * of the element information item is ·valid· with respect
15893 * to that simple type definition as defined by String
15894 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015895 */
15896 /*
15897 * STREAM: Children are processed.
15898 */
15899 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015900 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015901 /*
15902 * TODO: Could the entity stuff produce elements
15903 * as well?
15904 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015905 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015906 xmlSchemaVComplexTypeErr(ctxt,
15907 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015908 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015909 "Element content is not allowed, because "
15910 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015911 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15912 break;
15913 }
15914 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015915 }
15916 ctxt->node = elem;
15917 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015918 if (ret == 0) {
15919 /*
15920 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000015921 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015922 /*
15923 * STREAM: Children are processed.
15924 */
15925 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015926 value = NULL;
15927 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015928 value = xmlNodeGetContent(elem);
15929 /*
15930 * URGENT TODO: Should facets for the simple type validation be
15931 * disabled, if the derivation of facets for complex types
15932 * is implemented?
15933 */
15934 /*
15935 * NOTE: This call won't check the correct types of the
15936 * content nodes, since this should be done here.
15937 */
15938 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015939 if (ret > 0) {
15940 /*
15941 * NOTE: Although an error will be reported by
15942 * xmlSchemaValidateSimpleTypeValue, the spec wants
15943 * a specific complex type error to be reported
15944 * additionally.
15945 */
15946 xmlSchemaVComplexTypeErr(ctxt,
15947 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015948 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015949 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015950 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15951 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015952 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015953 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015954 "Element '%s': Error while validating character "
15955 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015956 elem->name, type->name);
15957 if (value != NULL)
15958 xmlFree(value);
15959 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015960 return (-1);
15961 }
William M. Brack2f2a6632004-08-20 23:09:47 +000015962 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015963 if (ret == 0) {
15964 /*
15965 * Apply facets of the complexType. Be sure to pass the
15966 * built-in type to xmlSchemaValidateFacetsInternal.
15967 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015968 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000015969 * are used, or if the facets, defined by this complex type,
15970 * are to be used only. This here applies both facet sets.
15971 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015972
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015973 ret = xmlSchemaValidateFacetsInternal(ctxt,
15974 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015975 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015976 xmlSchemaVComplexTypeErr(ctxt,
15977 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015978 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015979 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015980 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15981 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015982 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015983 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015984 "Element '%s': Error while validating character "
15985 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000015986 "apply facets.\n",
15987 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015988 if (value != NULL)
15989 xmlFree(value);
15990 ctxt->type = oldtype;
15991 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015992 }
15993 }
15994 if (value != NULL)
15995 xmlFree(value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015996
Daniel Veillard01fa6152004-06-29 17:04:39 +000015997 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015998 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015999 default:
16000 TODO xmlGenericError(xmlGenericErrorContext,
16001 "unimplemented content type %d\n",
16002 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016003 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016004 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016005 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016006}
16007
16008/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016009 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016010 * @ctxt: a schema validation context
16011 * @elem: an element
16012 * @type: the list of type declarations
16013 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016014 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016015 *
16016 * Returns 0 if the element is schemas valid, a positive error code
16017 * number otherwise and -1 in case of internal or API error.
16018 */
16019static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016020xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016021 xmlSchemaTypePtr type,
16022 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016023{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016024 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016025
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016026
16027 if ((ctxt == NULL) || (type == NULL)) {
16028 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16029 "Internal error: xmlSchemaValidateElementByType, "
16030 "bad arguments", NULL);
16031 return (-1);
16032 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016033 /*
16034 * This one is called by "xmlSchemaValidateElementByDeclaration".
16035 * It will forward to the proper validation
16036 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016037 */
16038 if (type == NULL) {
16039 xmlSchemaVComplexTypeErr(ctxt,
16040 XML_SCHEMAV_CVC_TYPE_1,
16041 ctxt->node, NULL,
16042 "The type definition is absent");
16043 return (XML_SCHEMAV_CVC_TYPE_1);
16044 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016045
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016046 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
16047 xmlSchemaVComplexTypeErr(ctxt,
16048 XML_SCHEMAV_CVC_TYPE_2,
16049 ctxt->node, type,
16050 "The type definition is abstract");
16051 return (XML_SCHEMAV_CVC_TYPE_2);
16052 }
16053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016054 switch (type->type) {
16055 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016056 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16057 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016058 break;
16059 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016060 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16061 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016062 break;
16063 case XML_SCHEMA_TYPE_BASIC:
16064 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16065 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16066 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016067 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16068 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016069 break;
16070 default:
16071 ret = -1;
16072 break;
16073 }
16074 if (ret == -1)
16075 return (-1);
16076 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016077 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016078}
16079
16080
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016081static int
16082xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16083 xmlSchemaAttributePtr decl,
16084 xmlSchemaAttrStatePtr state,
16085 xmlAttrPtr attr)
16086{
16087 xmlChar *value;
16088 const xmlChar *defValue;
16089 xmlSchemaValPtr defVal;
16090 int fixed;
16091 int ret;
16092
16093 if (decl->subtypes == NULL) {
16094 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16095 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16096 }
16097 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16098 ctxt->node = (xmlNodePtr) attr;
16099 ctxt->cur = attr->children;
16100 /*
16101 * NOTE: This call also checks the content nodes for correct type.
16102 */
16103 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16104 value, 1, 1, 1, 1);
16105
16106 /*
16107 * Handle 'fixed' attributes.
16108 */
16109 if (ret > 0) {
16110 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16111 /*
16112 * NOTE: Fixed value constraints will be not
16113 * applied if the value was invalid, because:
16114 * 1. The validation process does not return a precomputed
16115 * value.
16116 * 2. An invalid value implies a violation of a fixed
16117 * value constraint.
16118 */
16119 } else if (ret == 0) {
16120 state->state = XML_SCHEMAS_ATTR_CHECKED;
16121 if (xmlSchemaGetEffectiveValueConstraint(decl,
16122 &fixed, &defValue, &defVal) && (fixed == 1)) {
16123 /*
16124 * cvc-au : Attribute Locally Valid (Use)
16125 * For an attribute information item to be·valid·
16126 * with respect to an attribute use its ·normalized
16127 * value· must match the canonical lexical representation
16128 * of the attribute use's {value constraint} value, if it
16129 * is present and fixed.
16130 */
16131 /*
16132 * NOTE: the validation context holds in ctxt->value the
16133 * precomputed value of the attribute; well for some types,
16134 * fallback to string comparison if no computed value
16135 * exists.
16136 */
16137 if (((ctxt->value != NULL) &&
16138 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16139 ((ctxt->value == NULL) &&
16140 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16141 state->state =
16142 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16143 }
16144 }
16145 }
16146 if (value != NULL) {
16147 xmlFree(value);
16148 }
16149 return (ret);
16150}
16151
Daniel Veillard4255d502002-04-16 15:50:10 +000016152/**
16153 * xmlSchemaValidateAttributes:
16154 * @ctxt: a schema validation context
16155 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016156 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016157 *
16158 * Validate the attributes of an element.
16159 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016160 * 1. Existent, invalid attributes are reported in the form
16161 * "prefix:localName".
16162 * Reason: readability - it is easier to find the actual XML
16163 * representation of the attributes QName.
16164 * 2. Missing attributes are reported in the form
16165 * {"URI", "localName"}.
16166 * This is necessary, since the the prefix need not to be declared
16167 * at all, and thus is not computable.
16168 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016169 * Returns 0 if the element is schemas valid, a positive error code
16170 * number otherwise and -1 in case of internal or API error.
16171 */
16172static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016173xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016174{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016175 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016176 int ret;
16177 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016178 const xmlChar *defValue;
16179 xmlSchemaValPtr defVal;
16180 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016181 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016182 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016183 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016184 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016185 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016186 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016187#ifdef DEBUG_ATTR_VALIDATION
16188 int redundant = 0;
16189#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016190
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016191
Daniel Veillardc0826a72004-08-10 14:17:33 +000016192 /*
16193 * Allow all attributes if the type is anyType.
16194 */
16195 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16196 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016197
16198 oldnode = ctxt->node;
16199 if (type != NULL)
16200 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016201 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016202 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016203 attrDecl = attrUse->attr;
16204#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016205 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016206 printf("attr use - use: %d\n", attrDecl->occurs);
16207#endif
16208 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16209
16210 if (curState->decl == attrUse->attr) {
16211#ifdef DEBUG_ATTR_VALIDATION
16212 redundant = 1;
16213#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016214 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016215 attr = curState->attr;
16216#ifdef DEBUG_ATTR_VALIDATION
16217 printf("attr - name: %s\n", attr->name);
16218 if (attr->ns != NULL)
16219 printf("attr - ns: %s\n", attr->ns->href);
16220 else
16221 printf("attr - ns: none\n");
16222#endif
16223 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016224 if (attr == NULL)
16225 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016226 if (attrDecl->ref != NULL) {
16227 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016228 continue;
16229 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016230 if ((attrDecl->refNs == NULL) ||
16231 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016232 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016233 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016234 continue;
16235 }
16236 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016237 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016238 continue;
16239 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016240 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016241 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016242 if (attr->ns == NULL) {
16243 /*
William M. Bracke7091952004-05-11 15:09:58 +000016244 * accept an unqualified attribute only if the target
16245 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016246 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016247 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016248 /*
16249 * This check was removed, since the target namespace
16250 * was evaluated during parsing and already took
16251 * "attributeFormDefault" into account.
16252 */
16253 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016254 continue;
16255 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016256 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016257 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016258 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016259 attr->ns->href))
16260 continue;
16261 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016262 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016263#ifdef DEBUG_ATTR_VALIDATION
16264 printf("found\n");
16265#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016266 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016267 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016268 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016269 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016270 if (!found) {
16271 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16272 xmlSchemaAttrStatePtr tmp;
16273
Daniel Veillard3646d642004-06-02 19:19:14 +000016274#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016275 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016276#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016277 /*
16278 * Add a new dummy attribute state.
16279 */
16280 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16281 if (tmp == NULL) {
16282 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16283 ctxt->node = oldnode;
16284 return (-1);
16285 }
16286 tmp->attr = NULL;
16287 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16288 tmp->decl = attrDecl;
16289 tmp->next = NULL;
16290
16291 if (reqAttrStates == NULL) {
16292 reqAttrStates = tmp;
16293 reqAttrStatesTop = tmp;
16294 } else {
16295 reqAttrStatesTop->next = tmp;
16296 reqAttrStatesTop = tmp;
16297 }
16298 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16299 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16300 &fixed, &defValue, &defVal))) {
16301 xmlSchemaAttrStatePtr tmp;
16302 /*
16303 * Handle non existent default/fixed attributes.
16304 */
16305 tmp = (xmlSchemaAttrStatePtr)
16306 xmlMalloc(sizeof(xmlSchemaAttrState));
16307 if (tmp == NULL) {
16308 xmlSchemaVErrMemory(ctxt,
16309 "registering schema specified attributes", NULL);
16310 ctxt->node = oldnode;
16311 return (-1);
16312 }
16313 tmp->attr = NULL;
16314 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16315 tmp->decl = attrDecl;
16316 tmp->value = defValue;
16317 tmp->next = NULL;
16318
16319 if (defAttrStates == NULL) {
16320 defAttrStates = tmp;
16321 defAttrStates = tmp;
16322 } else {
16323 defAttrStates->next = tmp;
16324 defAttrStatesTop = tmp;
16325 }
16326 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016327 }
16328 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016329 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016330 /*
16331 * Add required attributes to the attribute states of the context.
16332 */
16333 if (reqAttrStates != NULL) {
16334 if (ctxt->attr == NULL) {
16335 ctxt->attr = reqAttrStates;
16336 } else {
16337 ctxt->attrTop->next = reqAttrStates;
16338 }
16339 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016340 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016341 /*
16342 * Process wildcards.
16343 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016344
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016345 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016346#ifdef DEBUG_ATTR_VALIDATION
16347 xmlSchemaWildcardNsPtr ns;
16348 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016349 if (type->attributeWildcard->processContents ==
16350 XML_SCHEMAS_ANY_LAX)
16351 printf("processContents: lax\n");
16352 else if (type->attributeWildcard->processContents ==
16353 XML_SCHEMAS_ANY_STRICT)
16354 printf("processContents: strict\n");
16355 else
16356 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016357 if (type->attributeWildcard->any)
16358 printf("type: any\n");
16359 else if (type->attributeWildcard->negNsSet != NULL) {
16360 printf("type: negated\n");
16361 if (type->attributeWildcard->negNsSet->value == NULL)
16362 printf("ns: (absent)\n");
16363 else
16364 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16365 } else if (type->attributeWildcard->nsSet != NULL) {
16366 printf("type: set\n");
16367 ns = type->attributeWildcard->nsSet;
16368 while (ns != NULL) {
16369 if (ns->value == NULL)
16370 printf("ns: (absent)\n");
16371 else
16372 printf("ns: %s\n", ns->value);
16373 ns = ns->next;
16374 }
16375 } else
16376 printf("empty\n");
16377
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016378
16379#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016380 curState = ctxt->attr;
16381 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016382 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16383 if (curState->attr->ns != NULL)
16384 nsURI = curState->attr->ns->href;
16385 else
16386 nsURI = NULL;
16387 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16388 nsURI)) {
16389 /*
16390 * Handle processContents.
16391 */
16392 if ((type->attributeWildcard->processContents ==
16393 XML_SCHEMAS_ANY_LAX) ||
16394 (type->attributeWildcard->processContents ==
16395 XML_SCHEMAS_ANY_STRICT)) {
16396
16397 attr = curState->attr;
16398 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016399 attr->name, nsURI);
16400 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016401 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016402 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016403 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016404 } else if (type->attributeWildcard->processContents ==
16405 XML_SCHEMAS_ANY_LAX) {
16406 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16407 }
16408 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016409 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016410 }
16411 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016412 curState = curState->next;
16413 }
16414 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016415
Daniel Veillardc0826a72004-08-10 14:17:33 +000016416 /*
16417 * Report missing and illegal attributes.
16418 */
16419 if (ctxt->attr != NULL) {
16420 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016421 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016422 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16423 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016424 if (curState->decl != NULL) {
16425 if (curState->decl->ref != NULL)
16426 attrDecl = curState->decl->refDecl;
16427 else
16428 attrDecl = curState->decl;
16429 } else
16430 attrDecl = NULL;
16431 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16432 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16433 } else if (curState->state ==
16434 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16435 xmlSchemaVCustomErr(ctxt,
16436 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16437 (xmlNodePtr) attr,
16438 (xmlSchemaTypePtr) attrDecl,
16439 "The type definition is absent",
16440 NULL);
16441 } else if (curState->state ==
16442 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16443 xmlSchemaVCustomErr(ctxt,
16444 XML_SCHEMAV_CVC_AU,
16445 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16446 "The value does not match the fixed value "
16447 "constraint", NULL);
16448 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016449 /* TODO: "prohibited" won't ever be touched here!.
16450 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16451 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016452 /*
16453 * TODO: One might report different error messages
16454 * for the following errors.
16455 */
16456 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016457 xmlSchemaVIllegalAttrErr(ctxt,
16458 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16459 } else {
16460 xmlSchemaVIllegalAttrErr(ctxt,
16461 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16462 }
16463 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016464 }
16465 curState = curState->next;
16466 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016467 }
16468
16469 /*
16470 * Add missing default/fixed attributes.
16471 */
16472 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16473 curState = defAttrStates;
16474 while (curState != NULL) {
16475 attrDecl = curState->decl;
16476 if (attrDecl->ref != NULL)
16477 attrDecl = attrDecl->refDecl;
16478 /*
16479 * PSVI: Add a new attribute node to the current element.
16480 */
16481 if (attrDecl->targetNamespace == NULL) {
16482 xmlNewProp(elem, attrDecl->name, curState->value);
16483 } else {
16484 xmlNsPtr ns;
16485
16486 ns = xmlSearchNsByHref(elem->doc, elem,
16487 attrDecl->targetNamespace);
16488 if (ns == NULL) {
16489 xmlChar prefix[12];
16490 int counter = 1;
16491
16492 attr = curState->attr;
16493 /*
16494 * Create a namespace declaration on the validation
16495 * root node if no namespace declaration is in scope.
16496 */
16497 snprintf((char *) prefix, sizeof(prefix), "p");
16498 /*
16499 * This is somehow not performant, since the ancestor
16500 * axis beyond @elem will be searched as well.
16501 */
16502 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16503 while (ns != NULL) {
16504 if (counter > 1000) {
16505 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16506 XML_SCHEMAV_INTERNAL,
16507 "Internal error: xmlSchemaValidateAttributes, "
16508 "could not compute a ns prefix for "
16509 "default/fixed attribute '%s'.\n",
16510 attrDecl->name, NULL);
16511
16512 break;
16513 }
16514 snprintf((char *) prefix,
16515 sizeof(prefix), "p%d", counter++);
16516 ns = xmlSearchNs(elem->doc, elem,
16517 BAD_CAST prefix);
16518 }
16519 if (ns == NULL) {
16520 ns = xmlNewNs(ctxt->validationRoot,
16521 attrDecl->targetNamespace, BAD_CAST prefix);
16522 xmlNewNsProp(elem, ns, attrDecl->name,
16523 curState->value);
16524 }
16525 } else {
16526 xmlNewNsProp(elem, ns, attrDecl->name,
16527 curState->value);
16528 }
16529 }
16530 curState = curState->next;
16531 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016532 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016533 if (defAttrStates != NULL)
16534 xmlSchemaFreeAttributeStates(defAttrStates);
16535
Daniel Veillard3646d642004-06-02 19:19:14 +000016536#ifdef DEBUG_ATTR_VALIDATION
16537 if (redundant)
16538 xmlGenericError(xmlGenericErrorContext,
16539 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16540 type->name);
16541#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016542 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016543 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016544}
16545
16546/**
16547 * xmlSchemaValidateElement:
16548 * @ctxt: a schema validation context
16549 * @elem: an element
16550 *
16551 * Validate an element in a tree
16552 *
16553 * Returns 0 if the element is schemas valid, a positive error code
16554 * number otherwise and -1 in case of internal or API error.
16555 */
16556static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016557xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016558{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016559 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016560 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016561
Daniel Veillardc0826a72004-08-10 14:17:33 +000016562 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016563 * This one is called by xmlSchemaValidateDocument and
16564 * xmlSchemaValidateOneElement.
16565 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016566 if (ctxt->schema == NULL) {
16567 /*
16568 * No schema was specified at time of creation of the validation
16569 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16570 * of the instance to build a schema.
16571 */
16572 if (ctxt->pctxt == NULL)
16573 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16574 if (ctxt->pctxt == NULL)
16575 return (-1);
16576 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16577 if (ctxt->schema == NULL)
16578 return (-1);
16579 /* TODO: assign user data. */
16580 ctxt->pctxt->error = ctxt->error;
16581 ctxt->pctxt->warning = ctxt->warning;
16582 ctxt->xsiAssemble = 1;
16583 } else
16584 ctxt->xsiAssemble = 0;
16585 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16586 * ctxt->xsiAssemble = 1;
16587 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016588 /*
16589 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016590 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016591 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016592 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16593 if (ret == -1) {
16594 xmlSchemaVCustomErr(ctxt,
16595 XML_SCHEMAV_INTERNAL,
16596 ctxt->node, NULL,
16597 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016598 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016599 }
16600 /*
16601 * NOTE: We won't react on schema parser errors here.
16602 * TODO: But a warning would be nice.
16603 */
16604 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016605 if (ret != -1) {
16606 if (ctxt->node->ns != NULL)
16607 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16608 ctxt->node->ns->href);
16609 else
16610 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16611
16612 if (elemDecl == NULL) {
16613 xmlSchemaVCustomErr(ctxt,
16614 XML_SCHEMAV_CVC_ELT_1,
16615 ctxt->node, NULL,
16616 "No matching global declaration available", NULL);
16617 ret = XML_SCHEMAV_CVC_ELT_1;
16618 } else {
16619 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16620 if (ret < 0) {
16621 xmlSchemaVCustomErr(ctxt,
16622 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16623 "Internal error: xmlSchemaValidateElement, "
16624 "calling validation by declaration", NULL);
16625 }
16626 }
16627 }
16628 /* ctxt->xsiAssemble = 0; */
16629 if (ctxt->xsiAssemble) {
16630 if (ctxt->schema != NULL) {
16631 xmlSchemaFree(ctxt->schema);
16632 ctxt->schema = NULL;
16633 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016634 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016635 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016636}
16637
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016638
Daniel Veillard4255d502002-04-16 15:50:10 +000016639/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016640 * xmlSchemaValidateOneElement:
16641 * @ctxt: a schema validation context
16642 * @elem: an element node
16643 *
16644 * Validate a branch of a tree, starting with the given @elem.
16645 *
16646 * Returns 0 if the element and its subtree is valid, a positive error
16647 * code number otherwise and -1 in case of an internal or API error.
16648 */
16649int
16650xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16651{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016652 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016653 return (-1);
16654
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016655 if (ctxt->schema == NULL) {
16656 xmlSchemaVErr(ctxt, NULL,
16657 XML_SCHEMAV_INTERNAL,
16658 "API error: xmlSchemaValidateOneElement, "
16659 "no schema specified.\n", NULL, NULL);
16660 return (-1);
16661 }
16662
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016663 ctxt->doc = elem->doc;
16664 ctxt->err = 0;
16665 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016666 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016667 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016668 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016669}
16670
16671/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016672 * xmlSchemaValidateDocument:
16673 * @ctxt: a schema validation context
16674 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016675 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016676 *
16677 * Validate a document tree in memory.
16678 *
16679 * Returns 0 if the document is schemas valid, a positive error code
16680 * number otherwise and -1 in case of internal or API error.
16681 */
16682static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016683xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16684{
Daniel Veillard4255d502002-04-16 15:50:10 +000016685 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016686
Daniel Veillard4255d502002-04-16 15:50:10 +000016687 root = xmlDocGetRootElement(doc);
16688 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016689 xmlSchemaVCustomErr(ctxt,
16690 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16691 (xmlNodePtr) doc, NULL,
16692 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016693 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016694 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016695 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016696 /*
16697 * Okay, start the recursive validation
16698 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016699 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016700 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016701 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016702
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016703 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016704}
16705
16706/************************************************************************
16707 * *
16708 * SAX Validation code *
16709 * *
16710 ************************************************************************/
16711
16712/************************************************************************
16713 * *
16714 * Validation interfaces *
16715 * *
16716 ************************************************************************/
16717
16718/**
16719 * xmlSchemaNewValidCtxt:
16720 * @schema: a precompiled XML Schemas
16721 *
16722 * Create an XML Schemas validation context based on the given schema
16723 *
16724 * Returns the validation context or NULL in case of error
16725 */
16726xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016727xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16728{
Daniel Veillard4255d502002-04-16 15:50:10 +000016729 xmlSchemaValidCtxtPtr ret;
16730
16731 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16732 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016733 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016734 return (NULL);
16735 }
16736 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016737 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016738 ret->attrTop = NULL;
16739 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016740 return (ret);
16741}
16742
16743/**
16744 * xmlSchemaFreeValidCtxt:
16745 * @ctxt: the schema validation context
16746 *
16747 * Free the resources associated to the schema validation context
16748 */
16749void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016750xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16751{
Daniel Veillard4255d502002-04-16 15:50:10 +000016752 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016753 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016754 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016755 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016756 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016757 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016758 if (ctxt->pctxt != NULL) {
16759 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16760 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016761 xmlFree(ctxt);
16762}
16763
16764/**
16765 * xmlSchemaSetValidErrors:
16766 * @ctxt: a schema validation context
16767 * @err: the error function
16768 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016769 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016770 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016771 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016772 */
16773void
16774xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016775 xmlSchemaValidityErrorFunc err,
16776 xmlSchemaValidityWarningFunc warn, void *ctx)
16777{
Daniel Veillard4255d502002-04-16 15:50:10 +000016778 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016779 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016780 ctxt->error = err;
16781 ctxt->warning = warn;
16782 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016783 if (ctxt->pctxt != NULL)
16784 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000016785}
16786
16787/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016788 * xmlSchemaGetValidErrors:
16789 * @ctxt: a XML-Schema validation context
16790 * @err: the error function result
16791 * @warn: the warning function result
16792 * @ctx: the functions context result
16793 *
16794 * Get the error and warning callback informations
16795 *
16796 * Returns -1 in case of error and 0 otherwise
16797 */
16798int
16799xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
16800 xmlSchemaValidityErrorFunc * err,
16801 xmlSchemaValidityWarningFunc * warn, void **ctx)
16802{
16803 if (ctxt == NULL)
16804 return (-1);
16805 if (err != NULL)
16806 *err = ctxt->error;
16807 if (warn != NULL)
16808 *warn = ctxt->warning;
16809 if (ctx != NULL)
16810 *ctx = ctxt->userData;
16811 return (0);
16812}
16813
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016814
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016815/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016816 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016817 * @ctxt: a schema validation context
16818 * @options: a combination of xmlSchemaValidOption
16819 *
16820 * Sets the options to be used during the validation.
16821 *
16822 * Returns 0 in case of success, -1 in case of an
16823 * API error.
16824 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016825int
16826xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
16827 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016828
16829{
16830 int i;
16831
16832 if (ctxt == NULL)
16833 return (-1);
16834 /*
16835 * WARNING: Change the start value if adding to the
16836 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016837 * TODO: Is there an other, more easy to maintain,
16838 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016839 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016840 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016841 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016842 xmlSchemaVErr(ctxt, NULL,
16843 XML_SCHEMAV_INTERNAL,
16844 "Internal error: xmlSchemaSetValidOptions, "
16845 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016846 return (-1);
16847 }
16848 }
16849 ctxt->options = options;
16850 return (0);
16851}
16852
16853/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016854 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016855 * @ctxt: a schema validation context
16856 *
16857 * Returns the option combination of the validation context.
16858 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016859int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016860xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
16861
16862{
16863 if (ctxt == NULL)
16864 return (-1);
16865 else
16866 return (ctxt->options);
16867}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016868
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016869
Daniel Veillard259f0df2004-08-18 09:13:18 +000016870/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016871 * xmlSchemaValidateDoc:
16872 * @ctxt: a schema validation context
16873 * @doc: a parsed document tree
16874 *
16875 * Validate a document tree in memory.
16876 *
16877 * Returns 0 if the document is schemas valid, a positive error code
16878 * number otherwise and -1 in case of internal or API error.
16879 */
16880int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016881xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16882{
Daniel Veillard4255d502002-04-16 15:50:10 +000016883 int ret;
16884
16885 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016886 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016887
16888 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000016889 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016890 ctxt->nberrors = 0;
16891
16892 /*
16893 if (ctxt->schema == NULL) {
16894 xmlSchemaVErr(ctxt, NULL,
16895 XML_SCHEMAV_INTERNAL,
16896 "API error: xmlSchemaValidateDoc, "
16897 "no schema specified and assembling of schemata "
16898 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
16899 "is not enabled.\n", NULL, NULL);
16900 return (-1);
16901 }
16902 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016903 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016904 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016905}
16906
16907/**
16908 * xmlSchemaValidateStream:
16909 * @ctxt: a schema validation context
16910 * @input: the input to use for reading the data
16911 * @enc: an optional encoding information
16912 * @sax: a SAX handler for the resulting events
16913 * @user_data: the context to provide to the SAX handler.
16914 *
16915 * Validate a document tree in memory.
16916 *
16917 * Returns 0 if the document is schemas valid, a positive error code
16918 * number otherwise and -1 in case of internal or API error.
16919 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016920int
Daniel Veillard4255d502002-04-16 15:50:10 +000016921xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016922 xmlParserInputBufferPtr input, xmlCharEncoding enc,
16923 xmlSAXHandlerPtr sax, void *user_data)
16924{
Daniel Veillard4255d502002-04-16 15:50:10 +000016925 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016926 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016927 ctxt->input = input;
16928 ctxt->enc = enc;
16929 ctxt->sax = sax;
16930 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016931 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000016932}
16933
16934#endif /* LIBXML_SCHEMAS_ENABLED */