blob: 81386b21bac3d0bd161e72416235ce633637293a [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000037
Daniel Veillarda84c0b32003-06-02 16:58:46 +000038/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000039
Daniel Veillard82bbbd42003-05-11 20:16:09 +000040/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000041
Daniel Veillard82bbbd42003-05-11 20:16:09 +000042/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000043
Daniel Veillard118aed72002-09-24 14:13:13 +000044/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000045
Daniel Veillard4255d502002-04-16 15:50:10 +000046/* #define DEBUG_AUTOMATA 1 */
47
Daniel Veillard3646d642004-06-02 19:19:14 +000048/* #define DEBUG_ATTR_VALIDATION 1 */
49
Daniel Veillardc0826a72004-08-10 14:17:33 +000050/* #define DEBUG_UNION_VALIDATION 1 */
51
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define UNBOUNDED (1 << 30)
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
William M. Brack2f2a6632004-08-20 23:09:47 +000059#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000060
Daniel Veillard4255d502002-04-16 15:50:10 +000061/*
62 * The XML Schemas namespaces
63 */
64static const xmlChar *xmlSchemaNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema";
66
67static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
68 "http://www.w3.org/2001/XMLSchema-instance";
69
Daniel Veillardc0826a72004-08-10 14:17:33 +000070static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
71 "Element decl.";
72static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
73 "Element ref.";
74static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
75 "Attribute decl.";
76static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
77 "Attribute ref.";
78static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000079 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000080static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000081 "complex type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000082
Daniel Veillard4255d502002-04-16 15:50:10 +000083#define IS_SCHEMA(node, type) \
84 ((node != NULL) && (node->ns != NULL) && \
85 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
86 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
87
Daniel Veillardc0826a72004-08-10 14:17:33 +000088#define FREE_AND_NULL(str) \
89 if (str != NULL) { \
90 xmlFree(str); \
91 str = NULL; \
92 }
93
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000094#define IS_ANYTYPE(item) \
95 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
96 (item->builtInType == XML_SCHEMAS_ANYTYPE))
97
98#define IS_COMPLEX_TYPE(item) \
99 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
100 (item->builtInType == XML_SCHEMAS_ANYTYPE))
101
102#define IS_SIMPLE_TYPE(item) \
103 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
104 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
105 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
106
Daniel Veillardc0826a72004-08-10 14:17:33 +0000107#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
108#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
109#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define XML_SCHEMAS_PARSE_ERROR 1
112
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000113#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000115
116/*
117* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
118* allow to assemble schemata with
119* the same target namespace from
120* different sources; otherwise, the first
121* encountered schema with a specific target
122* namespace will be used only *
123
124*
125* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
126* locate schemata to be imported
127* using the namespace name; otherwise
128* the location URI will be used */
129
130/*
131* xmlSchemaParserOption:
132*
133* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000135typedef enum {
136 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000137 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000138 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000139 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000140} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000141*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000142
143/*
144XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000145 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
146 int options);
147XMLPUBFUN int XMLCALL
148 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
149
150*/
151
152typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
153typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
154struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000155 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156 int nbItems; /* used for dynamic addition of schemata */
157 int sizeItems; /* used for dynamic addition of schemata */
158};
159
Daniel Veillard4255d502002-04-16 15:50:10 +0000160struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000161 void *userData; /* user specific data block */
162 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
163 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000164 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000165 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000166 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000167
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000168 xmlSchemaPtr topschema; /* The main schema */
169 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
170
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000171 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000172 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000173 int counter;
174
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000175 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000177 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000178
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179 const char *buffer;
180 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000181
Daniel Veillard4255d502002-04-16 15:50:10 +0000182 /*
183 * Used to build complex element content models
184 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000185 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 xmlAutomataStatePtr start;
187 xmlAutomataStatePtr end;
188 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000189
190 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000191 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000192 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
193 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194 xmlSchemaAssemblePtr assemble;
195 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000196 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000197};
198
199
200#define XML_SCHEMAS_ATTR_UNKNOWN 1
201#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000202#define XML_SCHEMAS_ATTR_PROHIBITED 3
203#define XML_SCHEMAS_ATTR_MISSING 4
204#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
205#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000206#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
207#define XML_SCHEMAS_ATTR_DEFAULT 8
Daniel Veillard4255d502002-04-16 15:50:10 +0000208
209typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
210typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
211struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000212 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000213 xmlAttrPtr attr;
214 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000215 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000216 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000217};
218
219/**
220 * xmlSchemaValidCtxt:
221 *
222 * A Schemas validation context
223 */
224
225struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *userData; /* user specific data block */
227 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
228 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000229 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000230
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000231 xmlSchemaPtr schema; /* The schema in use */
232 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlCharEncoding enc;
235 xmlSAXHandlerPtr sax;
236 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 xmlDocPtr myDoc;
239 int err;
240 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000241
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000242 xmlNodePtr node;
243 xmlNodePtr cur;
244 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000246 xmlRegExecCtxtPtr regexp;
247 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248
Daniel Veillard3646d642004-06-02 19:19:14 +0000249 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000250 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000251 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000252 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlNodePtr validationRoot;
255 xmlSchemaParserCtxtPtr pctxt;
256 int xsiAssemble;
Daniel Veillard4255d502002-04-16 15:50:10 +0000257};
258
Daniel Veillard1d913862003-11-21 00:28:39 +0000259/*
260 * These are the entries in the schemas importSchemas hash table
261 */
262typedef struct _xmlSchemaImport xmlSchemaImport;
263typedef xmlSchemaImport *xmlSchemaImportPtr;
264struct _xmlSchemaImport {
265 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000266 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000267 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000268 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000269};
Daniel Veillard4255d502002-04-16 15:50:10 +0000270
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000271/*
272 * These are the entries associated to includes in a schemas
273 */
274typedef struct _xmlSchemaInclude xmlSchemaInclude;
275typedef xmlSchemaInclude *xmlSchemaIncludePtr;
276struct _xmlSchemaInclude {
277 xmlSchemaIncludePtr next;
278
279 const xmlChar *schemaLocation;
280 xmlDocPtr doc;
281};
282
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000283typedef struct _xmlSchemaParticle xmlSchemaParticle;
284typedef xmlSchemaParticle *xmlSchemaParticlePtr;
285struct _xmlSchemaParticle {
286 xmlSchemaTypeType type;
287 xmlSchemaParticlePtr next; /* the next particle if in a list */
288 int minOccurs;
289 int maxOccurs;
290 xmlSchemaTypePtr term;
291};
292
293
294typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
295typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
296struct _xmlSchemaModelGroup {
297 xmlSchemaTypeType type;
298 int compositor; /* one of all, choice or sequence */
299 xmlSchemaParticlePtr particles; /* list of particles */
300 xmlSchemaAnnotPtr annot;
301};
302
303typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
304typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
305struct _xmlSchemaModelGroupDef {
306 xmlSchemaTypeType type;
307 const xmlChar *name;
308 const xmlChar *targetNamespace;
309 xmlSchemaModelGroupPtr modelGroup;
310 xmlSchemaAnnotPtr annot;
311};
312
Daniel Veillard4255d502002-04-16 15:50:10 +0000313/************************************************************************
314 * *
315 * Some predeclarations *
316 * *
317 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000319static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
320 xmlSchemaPtr schema,
321 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000322static void
323xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
324 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
325static const char *
326xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
327static int
328xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000329 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000330 const xmlChar *value,
331 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000332 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000333 int normalize,
334 int checkNodes);
335static int
336xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
337 xmlSchemaElementPtr elemDecl);
338static int
339xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
340 xmlSchemaTypePtr type);
341static int
342xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000343static int
344xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
345 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000346static void
347xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
348 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000349
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000350/************************************************************************
351 * *
352 * Datatype error handlers *
353 * *
354 ************************************************************************/
355
356/**
357 * xmlSchemaPErrMemory:
358 * @node: a context node
359 * @extra: extra informations
360 *
361 * Handle an out of memory condition
362 */
363static void
364xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
365 const char *extra, xmlNodePtr node)
366{
367 if (ctxt != NULL)
368 ctxt->nberrors++;
369 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
370 extra);
371}
372
373/**
374 * xmlSchemaPErr:
375 * @ctxt: the parsing context
376 * @node: the context node
377 * @error: the error code
378 * @msg: the error message
379 * @str1: extra data
380 * @str2: extra data
381 *
382 * Handle a parser error
383 */
384static void
385xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
386 const char *msg, const xmlChar * str1, const xmlChar * str2)
387{
388 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000389 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000390 void *data = NULL;
391
392 if (ctxt != NULL) {
393 ctxt->nberrors++;
394 channel = ctxt->error;
395 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000396 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000397 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000398 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000399 error, XML_ERR_ERROR, NULL, 0,
400 (const char *) str1, (const char *) str2, NULL, 0, 0,
401 msg, str1, str2);
402}
403
404/**
405 * xmlSchemaPErr2:
406 * @ctxt: the parsing context
407 * @node: the context node
408 * @node: the current child
409 * @error: the error code
410 * @msg: the error message
411 * @str1: extra data
412 * @str2: extra data
413 *
414 * Handle a parser error
415 */
416static void
417xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
418 xmlNodePtr child, int error,
419 const char *msg, const xmlChar * str1, const xmlChar * str2)
420{
421 if (child != NULL)
422 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
423 else
424 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
425}
426
Daniel Veillard01fa6152004-06-29 17:04:39 +0000427
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000428/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000429 * xmlSchemaPErrExt:
430 * @ctxt: the parsing context
431 * @node: the context node
432 * @error: the error code
433 * @strData1: extra data
434 * @strData2: extra data
435 * @strData3: extra data
436 * @msg: the message
437 * @str1: extra parameter for the message display
438 * @str2: extra parameter for the message display
439 * @str3: extra parameter for the message display
440 * @str4: extra parameter for the message display
441 * @str5: extra parameter for the message display
442 *
443 * Handle a parser error
444 */
445static void
446xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
447 const xmlChar * strData1, const xmlChar * strData2,
448 const xmlChar * strData3, const char *msg, const xmlChar * str1,
449 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
450 const xmlChar * str5)
451{
452
453 xmlGenericErrorFunc channel = NULL;
454 xmlStructuredErrorFunc schannel = NULL;
455 void *data = NULL;
456
457 if (ctxt != NULL) {
458 ctxt->nberrors++;
459 channel = ctxt->error;
460 data = ctxt->userData;
461 schannel = ctxt->serror;
462 }
463 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
464 error, XML_ERR_ERROR, NULL, 0,
465 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000466 (const char *) strData3, 0, 0, msg, str1, str2,
467 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000468}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000469
Daniel Veillard3646d642004-06-02 19:19:14 +0000470
471/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000472 * xmlSchemaVTypeErrMemory:
473 * @node: a context node
474 * @extra: extra informations
475 *
476 * Handle an out of memory condition
477 */
478static void
479xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
480 const char *extra, xmlNodePtr node)
481{
482 if (ctxt != NULL) {
483 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000484 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000485 }
486 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
487 extra);
488}
489
490/**
491 * xmlSchemaVErr3:
492 * @ctxt: the validation context
493 * @node: the context node
494 * @error: the error code
495 * @msg: the error message
496 * @str1: extra data
497 * @str2: extra data
498 * @str3: extra data
499 *
500 * Handle a validation error
501 */
502static void
503xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
504 const char *msg, const xmlChar *str1, const xmlChar *str2,
505 const xmlChar *str3)
506{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000507 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000508 xmlGenericErrorFunc channel = NULL;
509 void *data = NULL;
510
511 if (ctxt != NULL) {
512 ctxt->nberrors++;
513 ctxt->err = error;
514 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000515 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000516 data = ctxt->userData;
517 }
518 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000519 /* Removed, since the old schema error codes have been
520 * substituted for the global error codes.
521 *
522 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
523 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000524 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000525 error, XML_ERR_ERROR, NULL, 0,
526 (const char *) str1, (const char *) str2,
527 (const char *) str3, 0, 0,
528 msg, str1, str2, str3);
529}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000530
531/**
532 * xmlSchemaVErrExt:
533 * @ctxt: the validation context
534 * @node: the context node
535 * @error: the error code
536 * @msg: the message
537 * @str1: extra parameter for the message display
538 * @str2: extra parameter for the message display
539 * @str3: extra parameter for the message display
540 * @str4: extra parameter for the message display
541 * @str5: extra parameter for the message display
542 *
543 * Handle a validation error
544 */
545static void
546xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
547 const char *msg, const xmlChar * str1,
548 const xmlChar * str2, const xmlChar * str3,
549 const xmlChar * str4, const xmlChar * str5)
550{
551 xmlStructuredErrorFunc schannel = NULL;
552 xmlGenericErrorFunc channel = NULL;
553 void *data = NULL;
554
555 if (ctxt != NULL) {
556 ctxt->nberrors++;
557 ctxt->err = error;
558 channel = ctxt->error;
559 schannel = ctxt->serror;
560 data = ctxt->userData;
561 }
562 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000563 /* Removed, since the old schema error codes have been
564 * substituted for the global error codes.
565 *
566 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
567 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000568 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
569 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
570 msg, str1, str2, str3, str4, str5);
571}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572/**
573 * xmlSchemaVErr:
574 * @ctxt: the validation context
575 * @node: the context node
576 * @error: the error code
577 * @msg: the error message
578 * @str1: extra data
579 * @str2: extra data
580 *
581 * Handle a validation error
582 */
583static void
584xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
585 const char *msg, const xmlChar * str1, const xmlChar * str2)
586{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000587 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000588 xmlGenericErrorFunc channel = NULL;
589 void *data = NULL;
590
591 if (ctxt != NULL) {
592 ctxt->nberrors++;
593 ctxt->err = error;
594 channel = ctxt->error;
595 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000596 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000597 }
598 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000599 /* Removed, since the old schema error codes have been
600 * substituted for the global error codes.
601 *
602 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
603 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000604 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000605 error, XML_ERR_ERROR, NULL, 0,
606 (const char *) str1, (const char *) str2, NULL, 0, 0,
607 msg, str1, str2);
608}
Daniel Veillard4255d502002-04-16 15:50:10 +0000609
Daniel Veillardc0826a72004-08-10 14:17:33 +0000610/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000611 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000612 * @attr: the attribute declaration/use
613 *
614 * Returns the name of the attribute; if the attribute
615 * is a reference, the name of the referenced global type will be returned.
616 */
617static const xmlChar *
618xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
619{
620 if (attr->ref != NULL)
621 return(attr->ref);
622 else
623 return(attr->name);
624}
625
626/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000627 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000628 * @type: the type (element or attribute)
629 *
630 * Returns the target namespace URI of the type; if the type is a reference,
631 * the target namespace of the referenced type will be returned.
632 */
633static const xmlChar *
634xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
635{
636 if (attr->ref != NULL)
637 return (attr->refNs);
638 else
639 return(attr->targetNamespace);
640}
641
642/**
643 * xmlSchemaFormatNsUriLocal:
644 * @buf: the string buffer
645 * @uri: the namespace URI
646 * @local: the local name
647 *
648 * Returns a representation of the given URI used
649 * for error reports.
650 *
651 * Returns an empty string, if @ns is NULL, a formatted
652 * string otherwise.
653 */
654static const xmlChar*
655xmlSchemaFormatNsUriLocal(xmlChar **buf,
656 const xmlChar *uri, const xmlChar *local)
657{
658 if (*buf != NULL)
659 xmlFree(*buf);
660 if (uri == NULL) {
661 *buf = xmlStrdup(BAD_CAST "{'");
662 *buf = xmlStrcat(*buf, local);
663 } else {
664 *buf = xmlStrdup(BAD_CAST "{'");
665 *buf = xmlStrcat(*buf, uri);
666 *buf = xmlStrcat(*buf, BAD_CAST "', '");
667 *buf = xmlStrcat(*buf, local);
668 }
669 *buf = xmlStrcat(*buf, BAD_CAST "'}");
670 return ((const xmlChar *) *buf);
671}
672
673/**
674 * xmlSchemaFormatNsPrefixLocal:
675 * @buf: the string buffer
676 * @ns: the namespace
677 * @local: the local name
678 *
679 * Returns a representation of the given URI used
680 * for error reports.
681 *
682 * Returns an empty string, if @ns is NULL, a formatted
683 * string otherwise.
684 */
685static const xmlChar*
686xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
687 xmlNsPtr ns, const xmlChar *local)
688{
689 if (*buf != NULL) {
690 xmlFree(*buf);
691 *buf = NULL;
692 }
693 if ((ns == NULL) || (ns->prefix == NULL))
694 return(local);
695 else {
696 *buf = xmlStrdup(ns->prefix);
697 *buf = xmlStrcat(*buf, BAD_CAST ":");
698 *buf = xmlStrcat(*buf, local);
699 }
700 return ((const xmlChar *) *buf);
701}
702
703/**
704 * xmlSchemaFormatItemForReport:
705 * @buf: the string buffer
706 * @itemDes: the designation of the item
707 * @itemName: the name of the item
708 * @item: the item as an object
709 * @itemNode: the node of the item
710 * @local: the local name
711 * @parsing: if the function is used during the parse
712 *
713 * Returns a representation of the given item used
714 * for error reports.
715 *
716 * The following order is used to build the resulting
717 * designation if the arguments are not NULL:
718 * 1a. If itemDes not NULL -> itemDes
719 * 1b. If (itemDes not NULL) and (itemName not NULL)
720 * -> itemDes + itemName
721 * 2. If the preceding was NULL and (item not NULL) -> item
722 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
723 *
724 * If the itemNode is an attribute node, the name of the attribute
725 * will be appended to the result.
726 *
727 * Returns the formatted string and sets @buf to the resulting value.
728 */
729static xmlChar*
730xmlSchemaFormatItemForReport(xmlChar **buf,
731 const xmlChar *itemDes,
732 xmlSchemaTypePtr item,
733 xmlNodePtr itemNode,
734 int parsing)
735{
736 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000737 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000738
739 if (*buf != NULL) {
740 xmlFree(*buf);
741 *buf = NULL;
742 }
743
William M. Brack2f2a6632004-08-20 23:09:47 +0000744 if (itemDes != NULL) {
745 *buf = xmlStrdup(itemDes);
746 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000747 if (item->type == XML_SCHEMA_TYPE_BASIC) {
748 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
749 *buf = xmlStrdup(BAD_CAST "'anyType'");
750 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
751 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
752 else {
753 /* *buf = xmlStrdup(BAD_CAST "bi "); */
754 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
755 *buf = xmlStrdup(BAD_CAST "'");
756 *buf = xmlStrcat(*buf, item->name);
757 *buf = xmlStrcat(*buf, BAD_CAST "'");
758 }
759 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
760 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
761 *buf = xmlStrdup(xmlSchemaElemDesST);
762 *buf = xmlStrcat(*buf, BAD_CAST " '");
763 *buf = xmlStrcat(*buf, item->name);
764 *buf = xmlStrcat(*buf, BAD_CAST "'");
765 } else {
766 *buf = xmlStrdup(xmlSchemaElemDesST);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000767 /* Local types will get to name
768 *buf = xmlStrcat(*buf, BAD_CAST " ");
769 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000770 }
771 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
772 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
773 *buf = xmlStrdup(xmlSchemaElemDesCT);
774 *buf = xmlStrcat(*buf, BAD_CAST " '");
775 *buf = xmlStrcat(*buf, item->name);
776 *buf = xmlStrcat(*buf, BAD_CAST "'");
777 } else {
778 *buf = xmlStrdup(xmlSchemaElemDesCT);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000779 /* Local types will get to name
780 *buf = xmlStrcat(*buf, BAD_CAST " ");
781 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000782 }
783 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
784 xmlSchemaAttributePtr attr;
785
786 attr = (xmlSchemaAttributePtr) item;
787 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
788 (attr->ref == NULL)) {
789 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
790 *buf = xmlStrcat(*buf, BAD_CAST " '");
791 *buf = xmlStrcat(*buf, attr->name);
792 *buf = xmlStrcat(*buf, BAD_CAST "'");
793 } else {
794 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
795 *buf = xmlStrcat(*buf, BAD_CAST " '");
796 *buf = xmlStrcat(*buf, attr->refPrefix);
797 *buf = xmlStrcat(*buf, BAD_CAST ":");
798 *buf = xmlStrcat(*buf, attr->ref);
799 *buf = xmlStrcat(*buf, BAD_CAST "'");
800 }
801 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
802 xmlSchemaElementPtr elem;
803
804 elem = (xmlSchemaElementPtr) item;
805 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
806 (elem->ref == NULL)) {
807 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
808 *buf = xmlStrcat(*buf, BAD_CAST " '");
809 *buf = xmlStrcat(*buf, elem->name);
810 *buf = xmlStrcat(*buf, BAD_CAST "'");
811 } else {
812 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
813 *buf = xmlStrcat(*buf, BAD_CAST " '");
814 *buf = xmlStrcat(*buf, elem->refPrefix);
815 *buf = xmlStrcat(*buf, BAD_CAST ":");
816 *buf = xmlStrcat(*buf, elem->ref);
817 *buf = xmlStrcat(*buf, BAD_CAST "'");
818 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000819 } else
820 named = 0;
821 } else
822 named = 0;
823
824 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000825 xmlNodePtr elem;
826
827 if (itemNode->type == XML_ATTRIBUTE_NODE)
828 elem = itemNode->parent;
829 else
830 elem = itemNode;
831 *buf = xmlStrdup(BAD_CAST "Element '");
832 if (parsing)
833 *buf = xmlStrcat(*buf, elem->name);
834 else
835 *buf = xmlStrcat(*buf,
836 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
837 *buf = xmlStrcat(*buf, BAD_CAST "'");
838 }
839 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
840 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
841 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
842 itemNode->ns, itemNode->name));
843 *buf = xmlStrcat(*buf, BAD_CAST "'");
844 }
845 FREE_AND_NULL(str);
846
847 return (*buf);
848}
849
850/**
851 * xmlSchemaPFormatItemDes:
852 * @buf: the string buffer
853 * @item: the item as a schema object
854 * @itemNode: the item as a node
855 *
856 * If the pointer to @buf is not NULL and @but holds no value,
857 * the value is set to a item designation using
858 * xmlSchemaFormatItemForReport. This one avoids adding
859 * an attribute designation postfix.
860 *
861 * Returns a string of all enumeration elements.
862 */
863static void
864xmlSchemaPRequestItemDes(xmlChar **buf,
865 xmlSchemaTypePtr item,
866 xmlNodePtr itemNode)
867{
868 if ((buf == 0) || (*buf != NULL))
869 return;
870 if (itemNode->type == XML_ATTRIBUTE_NODE)
871 itemNode = itemNode->parent;
872 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
873}
874
875/**
876 * xmlSchemaFormatFacetEnumSet:
877 * @buf: the string buffer
878 * @type: the type holding the enumeration facets
879 *
880 * Builds a string consisting of all enumeration elements.
881 *
882 * Returns a string of all enumeration elements.
883 */
884static const xmlChar *
885xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
886{
887 xmlSchemaFacetLinkPtr link;
888
889 if (*buf != NULL)
890 xmlFree(*buf);
891 *buf = NULL;
892 for (link = type->facetSet; link != NULL; link = link->next) {
893 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
894 if (*buf == NULL) {
895 *buf = xmlStrdup(BAD_CAST "'");
896 *buf = xmlStrcat(*buf, link->facet->value);
897 *buf = xmlStrcat(*buf, BAD_CAST "'");
898 } else {
899 *buf = xmlStrcat(*buf, BAD_CAST ", '");
900 *buf = xmlStrcat(*buf, link->facet->value);
901 *buf = xmlStrcat(*buf, BAD_CAST "'");
902 }
903 }
904 }
905 return ((const xmlChar *) *buf);
906}
907
908/**
909 * xmlSchemaVFacetErr:
910 * @ctxt: the schema validation context
911 * @error: the error code
912 * @node: the node to be validated
913 * @value: the value of the node
914 * @type: the type holding the facet
915 * @facet: the facet
916 * @message: the error message of NULL
917 * @str1: extra data
918 * @str2: extra data
919 * @str3: extra data
920 *
921 * Reports a facet validation error.
922 * TODO: Should this report the value of an element as well?
923 */
924static void
925xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
926 xmlParserErrors error,
927 xmlNodePtr node,
928 const xmlChar *value,
929 unsigned long length,
930 xmlSchemaTypePtr type,
931 xmlSchemaFacetPtr facet,
932 const char *message,
933 const xmlChar *str1,
934 const xmlChar *str2,
935 const xmlChar *str3)
936{
937 xmlChar *str = NULL, *msg = NULL;
938 xmlSchemaTypeType facetType;
939
940 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
941 msg = xmlStrcat(msg, BAD_CAST " [");
942 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
943 msg = xmlStrcat(msg, BAD_CAST ", facet '");
944 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
945 facetType = XML_SCHEMA_FACET_ENUMERATION;
946 /*
947 * If enumerations are validated, one must not expect the
948 * facet to be given.
949 */
950 } else
951 facetType = facet->type;
952 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
953 msg = xmlStrcat(msg, BAD_CAST "']: ");
954 if (message == NULL) {
955 /*
956 * Use a default message.
957 */
958 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
959 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
960 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
961
962 char len[25], actLen[25];
963
964 /* FIXME, TODO: What is the max expected string length of the
965 * this value?
966 */
967 if (node->type == XML_ATTRIBUTE_NODE)
968 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
969 else
970 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
971
972 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
973 snprintf(actLen, 24, "%lu", length);
974
975 if (facetType == XML_SCHEMA_FACET_LENGTH)
976 msg = xmlStrcat(msg,
977 BAD_CAST "this differs from the allowed length of '%s'.\n");
978 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
979 msg = xmlStrcat(msg,
980 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
981 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
982 msg = xmlStrcat(msg,
983 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
984
985 if (node->type == XML_ATTRIBUTE_NODE)
986 xmlSchemaVErrExt(ctxt, node, error,
987 (const char *) msg,
988 value, (const xmlChar *) actLen, (const xmlChar *) len,
989 NULL, NULL);
990 else
991 xmlSchemaVErr(ctxt, node, error,
992 (const char *) msg,
993 (const xmlChar *) actLen, (const xmlChar *) len);
994
995 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
996 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
997 "of the set {%s}.\n");
998 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
999 xmlSchemaFormatFacetEnumSet(&str, type));
1000 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1001 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1002 "by the pattern '%s'.\n");
1003 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1004 facet->value);
1005 } else if (node->type == XML_ATTRIBUTE_NODE) {
1006 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1007 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1008 } else {
1009 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1010 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1011 }
1012 } else {
1013 msg = xmlStrcat(msg, (const xmlChar *) message);
1014 msg = xmlStrcat(msg, BAD_CAST ".\n");
1015 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1016 }
1017 FREE_AND_NULL(str)
1018 xmlFree(msg);
1019}
1020
1021/**
1022 * xmlSchemaVSimpleTypeErr:
1023 * @ctxt: the schema validation context
1024 * @error: the error code
1025 * @type: the type used for validation
1026 * @node: the node containing the validated value
1027 * @value: the validated value
1028 *
1029 * Reports a simple type validation error.
1030 * TODO: Should this report the value of an element as well?
1031 */
1032static void
1033xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1034 xmlParserErrors error,
1035 xmlNodePtr node,
1036 const xmlChar *value,
1037 xmlSchemaTypePtr type)
1038{
1039 xmlChar *str = NULL, *msg = NULL;
1040
1041 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1042 msg = xmlStrcat(msg, BAD_CAST " [");
1043 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1044 if (node->type == XML_ATTRIBUTE_NODE) {
1045 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1046 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1047 } else {
1048 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1049 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1050 }
1051 FREE_AND_NULL(str)
1052 xmlFree(msg);
1053}
1054
1055/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001056 * xmlSchemaVComplexTypeErr:
1057 * @ctxt: the schema validation context
1058 * @error: the error code
1059 * @node: the node containing the validated value
1060 * @type: the complex type used for validation
1061 * @message: the error message
1062 *
1063 * Reports a complex type validation error.
1064 */
1065static void
1066xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1067 xmlParserErrors error,
1068 xmlNodePtr node,
1069 xmlSchemaTypePtr type,
1070 const char *message)
1071{
1072 xmlChar *str = NULL, *msg = NULL;
1073
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001074 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001075 /* Specify the complex type only if it is global. */
1076 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001077 msg = xmlStrcat(msg, BAD_CAST " [");
1078 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1079 msg = xmlStrcat(msg, BAD_CAST "]");
1080 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001081 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1082 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001083 (const xmlChar *) message, NULL);
1084 FREE_AND_NULL(str)
1085 xmlFree(msg);
1086}
1087
1088/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001089 * xmlSchemaVComplexTypeElemErr:
1090 * @ctxt: the schema validation context
1091 * @error: the error code
1092 * @node: the node containing the validated value
1093 * @type: the complex type used for validation
1094 * @message: the error message
1095 *
1096 * Reports a complex type validation error.
1097 */
1098static void
1099xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1100 xmlParserErrors error,
1101 xmlNodePtr node,
1102 xmlSchemaTypePtr type,
1103 const char *message,
1104 int nbval,
1105 int nbneg,
1106 xmlChar **values)
1107{
1108 xmlChar *str = NULL, *msg = NULL;
1109 xmlChar *localName, *nsName;
1110 const xmlChar *cur, *end;
1111 int i;
1112
1113 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1114 /* Specify the complex type only if it is global. */
1115 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1116 msg = xmlStrcat(msg, BAD_CAST " [");
1117 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1118 msg = xmlStrcat(msg, BAD_CAST "]");
1119 FREE_AND_NULL(str)
1120 }
1121 msg = xmlStrcat(msg, BAD_CAST ": ");
1122 msg = xmlStrcat(msg, (const xmlChar *) message);
1123 /*
1124 * Note that is does not make sense to report that we have a
1125 * wildcard here, since the wildcard might be unfolded into
1126 * multiple transitions.
1127 */
1128 if (nbval + nbneg > 0) {
1129 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001130 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001131 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001132 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001133 nsName = NULL;
1134
1135 for (i = 0; i < nbval + nbneg; i++) {
1136 cur = values[i];
1137 /*
1138 * Get the local name.
1139 */
1140 localName = NULL;
1141
1142 end = cur;
1143 if (*end == '*') {
1144 localName = xmlStrdup(BAD_CAST "*");
1145 *end++;
1146 } else {
1147 while ((*end != 0) && (*end != '|'))
1148 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001149 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001150 }
1151 if (*end != 0) {
1152 *end++;
1153 /*
1154 * Skip "*|*" if they come with negated expressions, since
1155 * they represent the same negated wildcard.
1156 */
1157 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1158 /*
1159 * Get the namespace name.
1160 */
1161 cur = end;
1162 if (*end == '*') {
1163 nsName = xmlStrdup(BAD_CAST "{*}");
1164 } else {
1165 while (*end != 0)
1166 end++;
1167
1168 if (i >= nbval)
1169 nsName = xmlStrdup(BAD_CAST "{##other:");
1170 else
1171 nsName = xmlStrdup(BAD_CAST "{");
1172
1173 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1174 nsName = xmlStrcat(nsName, BAD_CAST "}");
1175 }
1176 str = xmlStrcat(str, BAD_CAST nsName);
1177 FREE_AND_NULL(nsName)
1178 } else {
1179 FREE_AND_NULL(localName);
1180 continue;
1181 }
1182 }
1183 str = xmlStrcat(str, BAD_CAST localName);
1184 FREE_AND_NULL(localName);
1185
1186 if (i < nbval + nbneg -1)
1187 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001188 }
1189 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001190 msg = xmlStrcat(msg, BAD_CAST str);
1191 FREE_AND_NULL(str)
1192 }
1193 msg = xmlStrcat(msg, BAD_CAST ".\n");
1194 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1195 xmlFree(msg);
1196}
1197
1198/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001199 * xmlSchemaPMissingAttrErr:
1200 * @ctxt: the schema validation context
1201 * @ownerDes: the designation of the owner
1202 * @ownerName: the name of the owner
1203 * @ownerItem: the owner as a schema object
1204 * @ownerElem: the owner as an element node
1205 * @node: the parent element node of the missing attribute node
1206 * @type: the corresponding type of the attribute node
1207 *
1208 * Reports an illegal attribute.
1209 */
1210static void
1211xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1212 xmlParserErrors error,
1213 xmlChar **ownerDes,
1214 xmlSchemaTypePtr ownerItem,
1215 xmlNodePtr ownerElem,
1216 const char *name,
1217 const char *message)
1218{
1219 xmlChar *des = NULL;
1220
1221 if (ownerDes == NULL)
1222 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1223 else if (*ownerDes == NULL) {
1224 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1225 des = *ownerDes;
1226 } else
1227 des = *ownerDes;
1228 if (message != NULL)
1229 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1230 else
1231 xmlSchemaPErr(ctxt, ownerElem, error,
1232 "%s: The attribute '%s' is required but missing.\n",
1233 BAD_CAST des, BAD_CAST name);
1234 if (ownerDes == NULL)
1235 FREE_AND_NULL(des);
1236}
1237
William M. Brack2f2a6632004-08-20 23:09:47 +00001238/**
1239 * xmlSchemaCompTypeToString:
1240 * @type: the type of the schema item
1241 *
1242 * Returns the component name of a schema item.
1243 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001244static const char *
1245xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1246{
1247 switch (type) {
1248 case XML_SCHEMA_TYPE_SIMPLE:
1249 return("simple type definition");
1250 case XML_SCHEMA_TYPE_COMPLEX:
1251 return("complex type definition");
1252 case XML_SCHEMA_TYPE_ELEMENT:
1253 return("element declaration");
1254 case XML_SCHEMA_TYPE_ATTRIBUTE:
1255 return("attribute declaration");
1256 case XML_SCHEMA_TYPE_GROUP:
1257 return("model group definition");
1258 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1259 return("attribute group definition");
1260 case XML_SCHEMA_TYPE_NOTATION:
1261 return("notation declaration");
1262 default:
1263 return("Not a schema component");
1264 }
1265}
1266/**
1267 * xmlSchemaPResCompAttrErr:
1268 * @ctxt: the schema validation context
1269 * @error: the error code
1270 * @ownerDes: the designation of the owner
1271 * @ownerItem: the owner as a schema object
1272 * @ownerElem: the owner as an element node
1273 * @name: the name of the attribute holding the QName
1274 * @refName: the referenced local name
1275 * @refURI: the referenced namespace URI
1276 * @message: optional message
1277 *
1278 * Used to report QName attribute values that failed to resolve
1279 * to schema components.
1280 */
1281static void
1282xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1283 xmlParserErrors error,
1284 xmlChar **ownerDes,
1285 xmlSchemaTypePtr ownerItem,
1286 xmlNodePtr ownerElem,
1287 const char *name,
1288 const xmlChar *refName,
1289 const xmlChar *refURI,
1290 xmlSchemaTypeType refType,
1291 const char *refTypeStr)
1292{
1293 xmlChar *des = NULL, *strA = NULL;
1294
1295 if (ownerDes == NULL)
1296 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1297 else if (*ownerDes == NULL) {
1298 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1299 des = *ownerDes;
1300 } else
1301 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001302 if (refTypeStr == NULL)
1303 refTypeStr = xmlSchemaCompTypeToString(refType);
1304 xmlSchemaPErrExt(ctxt, ownerElem, error,
1305 NULL, NULL, NULL,
1306 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1307 "%s.\n", BAD_CAST des, BAD_CAST name,
1308 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1309 BAD_CAST refTypeStr, NULL);
1310 if (ownerDes == NULL)
1311 FREE_AND_NULL(des)
1312 FREE_AND_NULL(strA)
1313}
1314
William M. Brack2f2a6632004-08-20 23:09:47 +00001315/**
1316 * xmlSchemaPCustomAttrErr:
1317 * @ctxt: the schema parser context
1318 * @error: the error code
1319 * @ownerDes: the designation of the owner
1320 * @ownerItem: the owner as a schema object
1321 * @attr: the illegal attribute node
1322 *
1323 * Reports an illegal attribute during the parse.
1324 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001325static void
1326xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001327 xmlParserErrors error,
1328 xmlChar **ownerDes,
1329 xmlSchemaTypePtr ownerItem,
1330 xmlAttrPtr attr,
1331 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001332{
1333 xmlChar *des = NULL;
1334
1335 if (ownerDes == NULL)
1336 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1337 else if (*ownerDes == NULL) {
1338 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1339 des = *ownerDes;
1340 } else
1341 des = *ownerDes;
1342 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1343 "%s, attribute '%s': %s.\n",
1344 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1345 if (ownerDes == NULL)
1346 FREE_AND_NULL(des);
1347}
1348
1349/**
1350 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001351 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001352 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001353 * @ownerDes: the designation of the attribute's owner
1354 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001355 * @attr: the illegal attribute node
1356 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001357 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001358 */
1359static void
1360xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1361 xmlParserErrors error,
1362 xmlChar **ownerDes,
1363 xmlSchemaTypePtr ownerItem,
1364 xmlAttrPtr attr)
1365{
1366 xmlChar *des = NULL, *strA = NULL;
1367
1368 if (ownerDes == NULL)
1369 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1370 else if (*ownerDes == NULL) {
1371 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1372 des = *ownerDes;
1373 } else
1374 des = *ownerDes;
1375 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1376 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1377 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1378 if (ownerDes == NULL)
1379 FREE_AND_NULL(des);
1380 FREE_AND_NULL(strA);
1381}
1382
William M. Brack2f2a6632004-08-20 23:09:47 +00001383/**
1384 * xmlSchemaPAquireDes:
1385 * @des: the first designation
1386 * @itemDes: the second designation
1387 * @item: the schema item
1388 * @itemElem: the node of the schema item
1389 *
1390 * Creates a designation for an item.
1391 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001392static void
1393xmlSchemaPAquireDes(xmlChar **des,
1394 xmlChar **itemDes,
1395 xmlSchemaTypePtr item,
1396 xmlNodePtr itemElem)
1397{
1398 if (itemDes == NULL)
1399 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1400 else if (*itemDes == NULL) {
1401 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1402 *des = *itemDes;
1403 } else
1404 *des = *itemDes;
1405}
1406
William M. Brack2f2a6632004-08-20 23:09:47 +00001407/**
1408 * xmlSchemaPCustomErr:
1409 * @ctxt: the schema parser context
1410 * @error: the error code
1411 * @itemDes: the designation of the schema item
1412 * @item: the schema item
1413 * @itemElem: the node of the schema item
1414 * @message: the error message
1415 * @str1: an optional param for the error message
1416 * @str2: an optional param for the error message
1417 * @str3: an optional param for the error message
1418 *
1419 * Reports an error during parsing.
1420 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001421static void
1422xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1423 xmlParserErrors error,
1424 xmlChar **itemDes,
1425 xmlSchemaTypePtr item,
1426 xmlNodePtr itemElem,
1427 const char *message,
1428 const xmlChar *str1,
1429 const xmlChar *str2,
1430 const xmlChar *str3)
1431{
1432 xmlChar *des = NULL, *msg = NULL;
1433
1434 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1435 msg = xmlStrdup(BAD_CAST "%s: ");
1436 msg = xmlStrcat(msg, (const xmlChar *) message);
1437 msg = xmlStrcat(msg, BAD_CAST ".\n");
1438 if ((itemElem == NULL) && (item != NULL))
1439 itemElem = item->node;
1440 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1441 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1442 if (itemDes == NULL)
1443 FREE_AND_NULL(des);
1444 FREE_AND_NULL(msg);
1445}
1446
William M. Brack2f2a6632004-08-20 23:09:47 +00001447/**
1448 * xmlSchemaPCustomErr:
1449 * @ctxt: the schema parser context
1450 * @error: the error code
1451 * @itemDes: the designation of the schema item
1452 * @item: the schema item
1453 * @itemElem: the node of the schema item
1454 * @message: the error message
1455 * @str1: the optional param for the error message
1456 *
1457 * Reports an error during parsing.
1458 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001459static void
1460xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1461 xmlParserErrors error,
1462 xmlChar **itemDes,
1463 xmlSchemaTypePtr item,
1464 xmlNodePtr itemElem,
1465 const char *message,
1466 const xmlChar *str1)
1467{
1468 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1469 str1, NULL, NULL);
1470}
1471
William M. Brack2f2a6632004-08-20 23:09:47 +00001472/**
1473 * xmlSchemaPAttrUseErr:
1474 * @ctxt: the schema parser context
1475 * @error: the error code
1476 * @itemDes: the designation of the schema type
1477 * @item: the schema type
1478 * @itemElem: the node of the schema type
1479 * @attr: the invalid schema attribute
1480 * @message: the error message
1481 * @str1: the optional param for the error message
1482 *
1483 * Reports an attribute use error during parsing.
1484 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001485static void
1486xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1487 xmlParserErrors error,
1488 xmlChar **itemDes,
1489 xmlSchemaTypePtr item,
1490 xmlNodePtr itemElem,
1491 const xmlSchemaAttributePtr attr,
1492 const char *message,
1493 const xmlChar *str1)
1494{
1495 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1496
1497 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1498 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1499 xmlSchemaGetAttrName(attr));
1500 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1501 msg = xmlStrcat(msg, (const xmlChar *) message);
1502 msg = xmlStrcat(msg, BAD_CAST ".\n");
1503 if ((itemElem == NULL) && (item != NULL))
1504 itemElem = item->node;
1505 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1506 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1507 if (itemDes == NULL)
1508 FREE_AND_NULL(des);
1509 FREE_AND_NULL(strA);
1510 xmlFree(msg);
1511}
1512
William M. Brack2f2a6632004-08-20 23:09:47 +00001513/**
1514 * xmlSchemaPIllegalFacetAtomicErr:
1515 * @ctxt: the schema parser context
1516 * @error: the error code
1517 * @itemDes: the designation of the type
1518 * @item: the schema type
1519 * @baseItem: the base type of type
1520 * @facet: the illegal facet
1521 *
1522 * Reports an illegal facet for atomic simple types.
1523 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001524static void
1525xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1526 xmlParserErrors error,
1527 xmlChar **itemDes,
1528 xmlSchemaTypePtr item,
1529 xmlSchemaTypePtr baseItem,
1530 xmlSchemaFacetPtr facet)
1531{
1532 xmlChar *des = NULL, *strT = NULL;
1533
1534 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1535 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1536 "%s: The facet '%s' is not allowed on types derived from the "
1537 "type %s.\n",
1538 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1539 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1540 NULL, NULL);
1541 if (itemDes == NULL)
1542 FREE_AND_NULL(des);
1543 FREE_AND_NULL(strT);
1544}
1545
William M. Brack2f2a6632004-08-20 23:09:47 +00001546/**
1547 * xmlSchemaPIllegalFacetListUnionErr:
1548 * @ctxt: the schema parser context
1549 * @error: the error code
1550 * @itemDes: the designation of the schema item involved
1551 * @item: the schema item involved
1552 * @facet: the illegal facet
1553 *
1554 * Reports an illegal facet for <list> and <union>.
1555 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001556static void
1557xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1558 xmlParserErrors error,
1559 xmlChar **itemDes,
1560 xmlSchemaTypePtr item,
1561 xmlSchemaFacetPtr facet)
1562{
1563 xmlChar *des = NULL, *strT = NULL;
1564
1565 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1566 xmlSchemaPErr(ctxt, item->node, error,
1567 "%s: The facet '%s' is not allowed.\n",
1568 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1569 if (itemDes == NULL)
1570 FREE_AND_NULL(des);
1571 FREE_AND_NULL(strT);
1572}
1573
1574/**
1575 * xmlSchemaPMutualExclAttrErr:
1576 * @ctxt: the schema validation context
1577 * @error: the error code
1578 * @elemDes: the designation of the parent element node
1579 * @attr: the bad attribute node
1580 * @type: the corresponding type of the attribute node
1581 *
1582 * Reports an illegal attribute.
1583 */
1584static void
1585xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1586 xmlParserErrors error,
1587 xmlChar **ownerDes,
1588 xmlSchemaTypePtr ownerItem,
1589 xmlAttrPtr attr,
1590 const char *name1,
1591 const char *name2)
1592{
1593 xmlChar *des = NULL;
1594
1595 if (ownerDes == NULL)
1596 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1597 else if (*ownerDes == NULL) {
1598 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1599 des = *ownerDes;
1600 } else
1601 des = *ownerDes;
1602 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1603 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1604 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1605 if (ownerDes == NULL)
1606 FREE_AND_NULL(des)
1607}
1608
1609/**
1610 * xmlSchemaPSimpleTypeErr:
1611 * @ctxt: the schema validation context
1612 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001613 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001614 * @ownerDes: the designation of the owner
1615 * @ownerItem: the schema object if existent
1616 * @node: the validated node
1617 * @value: the validated value
1618 *
1619 * Reports a simple type validation error.
1620 * TODO: Should this report the value of an element as well?
1621 */
1622static void
1623xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1624 xmlParserErrors error,
1625 xmlChar **ownerDes,
1626 xmlSchemaTypePtr ownerItem,
1627 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001628 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001629 const char *typeDes,
1630 const xmlChar *value,
1631 const char *message,
1632 const xmlChar *str1,
1633 const xmlChar *str2)
1634{
William M. Brack2f2a6632004-08-20 23:09:47 +00001635 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001636
1637 if (ownerDes == NULL)
1638 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1639 else if (*ownerDes == NULL) {
1640 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1641 des = *ownerDes;
1642 } else
1643 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001644 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001645 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001646 if (message == NULL) {
1647 /*
1648 * Use default messages.
1649 */
1650 if (node->type == XML_ATTRIBUTE_NODE) {
1651 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1652 "%s, attribute '%s' [%s]: The value '%s' is not "
1653 "valid.\n",
1654 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1655 node->name), BAD_CAST typeDes, value, NULL);
1656 } else {
1657 xmlSchemaPErr(ctxt, node, error,
1658 "%s [%s]: The character content is not valid.\n",
1659 BAD_CAST des, BAD_CAST typeDes);
1660 }
1661 } else {
1662 xmlChar *msg;
1663
1664 msg = xmlStrdup(BAD_CAST "%s");
1665 if (node->type == XML_ATTRIBUTE_NODE)
1666 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1667 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1668 msg = xmlStrcat(msg, (const xmlChar *) message);
1669 msg = xmlStrcat(msg, BAD_CAST ".\n");
1670 if (node->type == XML_ATTRIBUTE_NODE) {
1671 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1672 (const char *) msg,
1673 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1674 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1675 } else {
1676 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1677 (const char *) msg,
1678 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1679 }
1680 xmlFree(msg);
1681 }
1682 /* Cleanup. */
1683 FREE_AND_NULL(strA)
1684 FREE_AND_NULL(strT)
1685 if (ownerDes == NULL)
1686 FREE_AND_NULL(des)
1687}
1688
William M. Brack2f2a6632004-08-20 23:09:47 +00001689/**
1690 * xmlSchemaPContentErr:
1691 * @ctxt: the schema parser context
1692 * @error: the error code
1693 * @onwerDes: the designation of the holder of the content
1694 * @ownerItem: the owner item of the holder of the content
1695 * @ownerElem: the node of the holder of the content
1696 * @child: the invalid child node
1697 * @message: the optional error message
1698 * @content: the optional string describing the correct content
1699 *
1700 * Reports an error concerning the content of a schema element.
1701 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001702static void
1703xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1704 xmlParserErrors error,
1705 xmlChar **ownerDes,
1706 xmlSchemaTypePtr ownerItem,
1707 xmlNodePtr ownerElem,
1708 xmlNodePtr child,
1709 const char *message,
1710 const char *content)
1711{
1712 xmlChar *des = NULL;
1713
1714 if (ownerDes == NULL)
1715 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1716 else if (*ownerDes == NULL) {
1717 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1718 des = *ownerDes;
1719 } else
1720 des = *ownerDes;
1721 if (message != NULL)
1722 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1723 "%s: %s.\n",
1724 BAD_CAST des, BAD_CAST message);
1725 else {
1726 if (content != NULL) {
1727 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1728 "%s: The content is not valid. Expected is %s.\n",
1729 BAD_CAST des, BAD_CAST content);
1730 } else {
1731 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1732 "%s: The content is not valid.\n",
1733 BAD_CAST des, NULL);
1734 }
1735 }
1736 if (ownerDes == NULL)
1737 FREE_AND_NULL(des)
1738}
1739
1740/**
1741 * xmlSchemaVIllegalAttrErr:
1742 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001743 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001744 * @attr: the illegal attribute node
1745 *
1746 * Reports an illegal attribute.
1747 */
1748static void
1749xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001750 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001751 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001752{
1753 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001754
1755 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1756 error,
1757 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001758 "%s: The attribute '%s' is not allowed.\n",
1759 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1760 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1761 FREE_AND_NULL(strE)
1762 FREE_AND_NULL(strA)
1763}
1764
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001765
1766static int
1767xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1768{
1769 switch (item->type) {
1770 case XML_SCHEMA_TYPE_COMPLEX:
1771 case XML_SCHEMA_TYPE_SIMPLE:
1772 case XML_SCHEMA_TYPE_GROUP:
1773 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1774 return(1);
1775 break;
1776 case XML_SCHEMA_TYPE_ELEMENT:
1777 if ( ((xmlSchemaElementPtr) item)->flags &
1778 XML_SCHEMAS_ELEM_GLOBAL)
1779 return(1);
1780 break;
1781 case XML_SCHEMA_TYPE_ATTRIBUTE:
1782 if ( ((xmlSchemaAttributePtr) item)->flags &
1783 XML_SCHEMAS_ATTR_GLOBAL)
1784 return(1);
1785 break;
1786 /* Note that attribute groups are always global. */
1787 default:
1788 return(1);
1789 }
1790 return (0);
1791}
1792
William M. Brack2f2a6632004-08-20 23:09:47 +00001793/**
1794 * xmlSchemaVCustomErr:
1795 * @ctxt: the schema validation context
1796 * @error: the error code
1797 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001798 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001799 * @message: the error message
1800 * @str1: the optional param for the message
1801 *
1802 * Reports a validation error.
1803 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001804static void
1805xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1806 xmlParserErrors error,
1807 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001808 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001809 const char *message,
1810 const xmlChar *str1)
1811{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001812 xmlChar *msg = NULL, *str = NULL;
1813
1814 if (node == NULL) {
1815 xmlSchemaVErr(ctxt, NULL,
1816 XML_SCHEMAV_INTERNAL,
1817 "Internal error: xmlSchemaVCustomErr, no node "
1818 "given.\n", NULL, NULL);
1819 return;
1820 }
1821 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1822 if (node->type != XML_DOCUMENT_NODE) {
1823 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001824 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001825 msg = xmlStrcat(msg, BAD_CAST " [");
1826 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1827 msg = xmlStrcat(msg, BAD_CAST "]");
1828 }
1829 msg = xmlStrcat(msg, BAD_CAST ": ");
1830 } else
1831 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001832 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001833 msg = xmlStrcat(msg, BAD_CAST ".\n");
1834 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1835 FREE_AND_NULL(msg)
1836 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837}
1838
William M. Brack2f2a6632004-08-20 23:09:47 +00001839/**
1840 * xmlSchemaWildcardPCToString:
1841 * @pc: the type of processContents
1842 *
1843 * Returns a string representation of the type of
1844 * processContents.
1845 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001846static const char *
1847xmlSchemaWildcardPCToString(int pc)
1848{
1849 switch (pc) {
1850 case XML_SCHEMAS_ANY_SKIP:
1851 return ("skip");
1852 case XML_SCHEMAS_ANY_LAX:
1853 return ("lax");
1854 case XML_SCHEMAS_ANY_STRICT:
1855 return ("strict");
1856 default:
1857 return ("invalid process contents");
1858 }
1859}
1860
William M. Brack2f2a6632004-08-20 23:09:47 +00001861/**
1862 * xmlSchemaVWildcardErr:
1863 * @ctxt: the schema validation context
1864 * @error: the error code
1865 * @node: the validated node
1866 * @wild: the wildcard used
1867 * @message: the error message
1868 *
1869 * Reports an validation-by-wildcard error.
1870 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001871static void
1872xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1873 xmlParserErrors error,
1874 xmlNodePtr node,
1875 xmlSchemaWildcardPtr wild,
1876 const char *message)
1877{
1878 xmlChar *des = NULL, *msg = NULL;
1879
1880 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1881 msg = xmlStrdup(BAD_CAST "%s, [");
1882 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001883 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001884 msg = xmlStrcat(msg, (const xmlChar *) message);
1885 msg = xmlStrcat(msg, BAD_CAST ".\n");
1886 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1887 FREE_AND_NULL(des);
1888 FREE_AND_NULL(msg);
1889}
1890
1891/**
1892 * xmlSchemaVMissingAttrErr:
1893 * @ctxt: the schema validation context
1894 * @node: the parent element node of the missing attribute node
1895 * @type: the corresponding type of the attribute node
1896 *
1897 * Reports an illegal attribute.
1898 */
1899static void
1900xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1901 xmlNodePtr elem,
1902 xmlSchemaAttributePtr type)
1903{
1904 const xmlChar *name, *uri;
1905 xmlChar *strE = NULL, *strA = NULL;
1906
1907 if (type->ref != NULL) {
1908 name = type->ref;
1909 uri = type->refNs;
1910 } else {
1911 name = type->name;
1912 uri = type->targetNamespace;
1913 }
1914 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001915 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1916 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001917 "%s: The attribute %s is required but missing.\n",
1918 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1919 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1920 FREE_AND_NULL(strE)
1921 FREE_AND_NULL(strA)
1922}
1923
Daniel Veillard4255d502002-04-16 15:50:10 +00001924/************************************************************************
1925 * *
1926 * Allocation functions *
1927 * *
1928 ************************************************************************/
1929
1930/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001931 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001932 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001933 *
1934 * Allocate a new Schema structure.
1935 *
1936 * Returns the newly allocated structure or NULL in case or error
1937 */
1938static xmlSchemaPtr
1939xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1940{
1941 xmlSchemaPtr ret;
1942
1943 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1944 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001945 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001946 return (NULL);
1947 }
1948 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001949 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001950 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001951
1952 return (ret);
1953}
1954
1955/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001956 * xmlSchemaNewSchema:
1957 * @ctxt: a schema validation context
1958 *
1959 * Allocate a new Schema structure.
1960 *
1961 * Returns the newly allocated structure or NULL in case or error
1962 */
1963static xmlSchemaAssemblePtr
1964xmlSchemaNewAssemble(void)
1965{
1966 xmlSchemaAssemblePtr ret;
1967
1968 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1969 if (ret == NULL) {
1970 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1971 return (NULL);
1972 }
1973 memset(ret, 0, sizeof(xmlSchemaAssemble));
1974 ret->items = NULL;
1975 return (ret);
1976}
1977
1978/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001979 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001980 *
1981 * Allocate a new Facet structure.
1982 *
1983 * Returns the newly allocated structure or NULL in case or error
1984 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001985xmlSchemaFacetPtr
1986xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001987{
1988 xmlSchemaFacetPtr ret;
1989
1990 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1991 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001992 return (NULL);
1993 }
1994 memset(ret, 0, sizeof(xmlSchemaFacet));
1995
1996 return (ret);
1997}
1998
1999/**
2000 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002001 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002002 * @node: a node
2003 *
2004 * Allocate a new annotation structure.
2005 *
2006 * Returns the newly allocated structure or NULL in case or error
2007 */
2008static xmlSchemaAnnotPtr
2009xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2010{
2011 xmlSchemaAnnotPtr ret;
2012
2013 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2014 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002015 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002016 return (NULL);
2017 }
2018 memset(ret, 0, sizeof(xmlSchemaAnnot));
2019 ret->content = node;
2020 return (ret);
2021}
2022
2023/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002024 * xmlSchemaFreeAnnot:
2025 * @annot: a schema type structure
2026 *
2027 * Deallocate a annotation structure
2028 */
2029static void
2030xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2031{
2032 if (annot == NULL)
2033 return;
2034 xmlFree(annot);
2035}
2036
2037/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002038 * xmlSchemaFreeImport:
2039 * @import: a schema import structure
2040 *
2041 * Deallocate an import structure
2042 */
2043static void
2044xmlSchemaFreeImport(xmlSchemaImportPtr import)
2045{
2046 if (import == NULL)
2047 return;
2048
2049 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002050 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002051 xmlFree(import);
2052}
2053
2054/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002055 * xmlSchemaFreeInclude:
2056 * @include: a schema include structure
2057 *
2058 * Deallocate an include structure
2059 */
2060static void
2061xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2062{
2063 if (include == NULL)
2064 return;
2065
2066 xmlFreeDoc(include->doc);
2067 xmlFree(include);
2068}
2069
2070/**
2071 * xmlSchemaFreeIncludeList:
2072 * @includes: a schema include list
2073 *
2074 * Deallocate an include structure
2075 */
2076static void
2077xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2078{
2079 xmlSchemaIncludePtr next;
2080
2081 while (includes != NULL) {
2082 next = includes->next;
2083 xmlSchemaFreeInclude(includes);
2084 includes = next;
2085 }
2086}
2087
2088/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 * xmlSchemaFreeNotation:
2090 * @schema: a schema notation structure
2091 *
2092 * Deallocate a Schema Notation structure.
2093 */
2094static void
2095xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2096{
2097 if (nota == NULL)
2098 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002099 xmlFree(nota);
2100}
2101
2102/**
2103 * xmlSchemaFreeAttribute:
2104 * @schema: a schema attribute structure
2105 *
2106 * Deallocate a Schema Attribute structure.
2107 */
2108static void
2109xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2110{
2111 if (attr == NULL)
2112 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002113 if (attr->annot != NULL)
2114 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002115 if (attr->defVal != NULL)
2116 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002117 xmlFree(attr);
2118}
2119
2120/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002121 * xmlSchemaFreeWildcardNsSet:
2122 * set: a schema wildcard namespace
2123 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002124 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002125 */
2126static void
2127xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2128{
2129 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002130
Daniel Veillard3646d642004-06-02 19:19:14 +00002131 while (set != NULL) {
2132 next = set->next;
2133 xmlFree(set);
2134 set = next;
2135 }
2136}
2137
2138/**
2139 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002140 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002141 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002142 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002143 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002144void
Daniel Veillard3646d642004-06-02 19:19:14 +00002145xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2146{
2147 if (wildcard == NULL)
2148 return;
2149 if (wildcard->annot != NULL)
2150 xmlSchemaFreeAnnot(wildcard->annot);
2151 if (wildcard->nsSet != NULL)
2152 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2153 if (wildcard->negNsSet != NULL)
2154 xmlFree(wildcard->negNsSet);
2155 xmlFree(wildcard);
2156}
2157
2158/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 * xmlSchemaFreeAttributeGroup:
2160 * @schema: a schema attribute group structure
2161 *
2162 * Deallocate a Schema Attribute Group structure.
2163 */
2164static void
2165xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2166{
2167 if (attr == NULL)
2168 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002169 if (attr->annot != NULL)
2170 xmlSchemaFreeAnnot(attr->annot);
2171 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2172 (attr->attributeWildcard != NULL))
2173 xmlSchemaFreeWildcard(attr->attributeWildcard);
2174
Daniel Veillard4255d502002-04-16 15:50:10 +00002175 xmlFree(attr);
2176}
2177
2178/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002179 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002180 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002181 *
2182 * Deallocate a list of schema attribute uses.
2183 */
2184static void
2185xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2186{
2187 xmlSchemaAttributeLinkPtr next;
2188
2189 while (attrUse != NULL) {
2190 next = attrUse->next;
2191 xmlFree(attrUse);
2192 attrUse = next;
2193 }
2194}
2195
2196/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002197 * xmlSchemaFreeTypeLinkList:
2198 * @alink: a type link
2199 *
2200 * Deallocate a list of types.
2201 */
2202static void
2203xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2204{
2205 xmlSchemaTypeLinkPtr next;
2206
2207 while (link != NULL) {
2208 next = link->next;
2209 xmlFree(link);
2210 link = next;
2211 }
2212}
2213
2214/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002215 * xmlSchemaFreeElement:
2216 * @schema: a schema element structure
2217 *
2218 * Deallocate a Schema Element structure.
2219 */
2220static void
2221xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2222{
2223 if (elem == NULL)
2224 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002225 if (elem->annot != NULL)
2226 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002227 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002229 if (elem->defVal != NULL)
2230 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002231 xmlFree(elem);
2232}
2233
2234/**
2235 * xmlSchemaFreeFacet:
2236 * @facet: a schema facet structure
2237 *
2238 * Deallocate a Schema Facet structure.
2239 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002240void
Daniel Veillard4255d502002-04-16 15:50:10 +00002241xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2242{
2243 if (facet == NULL)
2244 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002245 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002246 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002247 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002249 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002250 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 xmlFree(facet);
2252}
2253
2254/**
2255 * xmlSchemaFreeType:
2256 * @type: a schema type structure
2257 *
2258 * Deallocate a Schema Type structure.
2259 */
2260void
2261xmlSchemaFreeType(xmlSchemaTypePtr type)
2262{
2263 if (type == NULL)
2264 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002265 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002266 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002267 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002268 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002269
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002270 facet = type->facets;
2271 while (facet != NULL) {
2272 next = facet->next;
2273 xmlSchemaFreeFacet(facet);
2274 facet = next;
2275 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002276 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002277 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2278 if (type->attributeUses != NULL)
2279 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002280 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002281 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002282 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2283 /*
2284 * NOTE: The only case where an attribute wildcard
2285 * is not owned, is if a complex type inherits it
2286 * from a base type.
2287 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002288 xmlSchemaFreeWildcard(type->attributeWildcard);
2289 }
2290 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002291 if (type->memberTypes != NULL)
2292 xmlSchemaFreeTypeLinkList(type->memberTypes);
2293 if (type->facetSet != NULL) {
2294 xmlSchemaFacetLinkPtr next, link;
2295
2296 link = type->facetSet;
2297 do {
2298 next = link->next;
2299 xmlFree(link);
2300 link = next;
2301 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002302 }
2303 if (type->contModel != NULL)
2304 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002305 xmlFree(type);
2306}
2307
2308/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002309 * xmlSchemaFreeTypeList:
2310 * @type: a schema type structure
2311 *
2312 * Deallocate a Schema Type structure.
2313 */
2314static void
2315xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2316{
2317 xmlSchemaTypePtr next;
2318
2319 while (type != NULL) {
2320 next = type->redef;
2321 xmlSchemaFreeType(type);
2322 type = next;
2323 }
2324}
2325
2326/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002327 * xmlSchemaFree:
2328 * @schema: a schema structure
2329 *
2330 * Deallocate a Schema structure.
2331 */
2332void
2333xmlSchemaFree(xmlSchemaPtr schema)
2334{
2335 if (schema == NULL)
2336 return;
2337
Daniel Veillard4255d502002-04-16 15:50:10 +00002338 if (schema->notaDecl != NULL)
2339 xmlHashFree(schema->notaDecl,
2340 (xmlHashDeallocator) xmlSchemaFreeNotation);
2341 if (schema->attrDecl != NULL)
2342 xmlHashFree(schema->attrDecl,
2343 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2344 if (schema->attrgrpDecl != NULL)
2345 xmlHashFree(schema->attrgrpDecl,
2346 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2347 if (schema->elemDecl != NULL)
2348 xmlHashFree(schema->elemDecl,
2349 (xmlHashDeallocator) xmlSchemaFreeElement);
2350 if (schema->typeDecl != NULL)
2351 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002352 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002353 if (schema->groupDecl != NULL)
2354 xmlHashFree(schema->groupDecl,
2355 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002356 if (schema->schemasImports != NULL)
2357 xmlHashFree(schema->schemasImports,
2358 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002359 if (schema->includes != NULL) {
2360 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2361 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002362 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002363 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002364 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002365 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002366 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002367 xmlFree(schema);
2368}
2369
2370/************************************************************************
2371 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002372 * Debug functions *
2373 * *
2374 ************************************************************************/
2375
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002376#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002377
Daniel Veillard4255d502002-04-16 15:50:10 +00002378/**
2379 * xmlSchemaElementDump:
2380 * @elem: an element
2381 * @output: the file output
2382 *
2383 * Dump the element
2384 */
2385static void
2386xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002387 const xmlChar * name ATTRIBUTE_UNUSED,
2388 const xmlChar * context ATTRIBUTE_UNUSED,
2389 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002390{
2391 if (elem == NULL)
2392 return;
2393
2394 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002395 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2396 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002397 fprintf(output, ": %s ", elem->name);
2398 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002399 fprintf(output, "namespace '%s' ", namespace);
2400
Daniel Veillard4255d502002-04-16 15:50:10 +00002401 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002402 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002403 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002404 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002405 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002406 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002407 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002408 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002409 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002410 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002411 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002412 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002413 fprintf(output, "\n");
2414 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 fprintf(output, " ");
2416 if (elem->minOccurs != 1)
2417 fprintf(output, "min: %d ", elem->minOccurs);
2418 if (elem->maxOccurs >= UNBOUNDED)
2419 fprintf(output, "max: unbounded\n");
2420 else if (elem->maxOccurs != 1)
2421 fprintf(output, "max: %d\n", elem->maxOccurs);
2422 else
2423 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002424 }
2425 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002426 fprintf(output, " type: %s", elem->namedType);
2427 if (elem->namedTypeNs != NULL)
2428 fprintf(output, " ns %s\n", elem->namedTypeNs);
2429 else
2430 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002431 }
2432 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002433 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2434 if (elem->substGroupNs != NULL)
2435 fprintf(output, " ns %s\n", elem->substGroupNs);
2436 else
2437 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002438 }
2439 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002440 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002441}
2442
2443/**
2444 * xmlSchemaAnnotDump:
2445 * @output: the file output
2446 * @annot: a annotation
2447 *
2448 * Dump the annotation
2449 */
2450static void
2451xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2452{
2453 xmlChar *content;
2454
2455 if (annot == NULL)
2456 return;
2457
2458 content = xmlNodeGetContent(annot->content);
2459 if (content != NULL) {
2460 fprintf(output, " Annot: %s\n", content);
2461 xmlFree(content);
2462 } else
2463 fprintf(output, " Annot: empty\n");
2464}
2465
2466/**
2467 * xmlSchemaTypeDump:
2468 * @output: the file output
2469 * @type: a type structure
2470 *
2471 * Dump a SchemaType structure
2472 */
2473static void
2474xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2475{
2476 if (type == NULL) {
2477 fprintf(output, "Type: NULL\n");
2478 return;
2479 }
2480 fprintf(output, "Type: ");
2481 if (type->name != NULL)
2482 fprintf(output, "%s, ", type->name);
2483 else
2484 fprintf(output, "no name");
2485 switch (type->type) {
2486 case XML_SCHEMA_TYPE_BASIC:
2487 fprintf(output, "basic ");
2488 break;
2489 case XML_SCHEMA_TYPE_SIMPLE:
2490 fprintf(output, "simple ");
2491 break;
2492 case XML_SCHEMA_TYPE_COMPLEX:
2493 fprintf(output, "complex ");
2494 break;
2495 case XML_SCHEMA_TYPE_SEQUENCE:
2496 fprintf(output, "sequence ");
2497 break;
2498 case XML_SCHEMA_TYPE_CHOICE:
2499 fprintf(output, "choice ");
2500 break;
2501 case XML_SCHEMA_TYPE_ALL:
2502 fprintf(output, "all ");
2503 break;
2504 case XML_SCHEMA_TYPE_UR:
2505 fprintf(output, "ur ");
2506 break;
2507 case XML_SCHEMA_TYPE_RESTRICTION:
2508 fprintf(output, "restriction ");
2509 break;
2510 case XML_SCHEMA_TYPE_EXTENSION:
2511 fprintf(output, "extension ");
2512 break;
2513 default:
2514 fprintf(output, "unknowntype%d ", type->type);
2515 break;
2516 }
2517 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002518 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002519 }
2520 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002521 case XML_SCHEMA_CONTENT_UNKNOWN:
2522 fprintf(output, "unknown ");
2523 break;
2524 case XML_SCHEMA_CONTENT_EMPTY:
2525 fprintf(output, "empty ");
2526 break;
2527 case XML_SCHEMA_CONTENT_ELEMENTS:
2528 fprintf(output, "element ");
2529 break;
2530 case XML_SCHEMA_CONTENT_MIXED:
2531 fprintf(output, "mixed ");
2532 break;
2533 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002534 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002535 break;
2536 case XML_SCHEMA_CONTENT_BASIC:
2537 fprintf(output, "basic ");
2538 break;
2539 case XML_SCHEMA_CONTENT_SIMPLE:
2540 fprintf(output, "simple ");
2541 break;
2542 case XML_SCHEMA_CONTENT_ANY:
2543 fprintf(output, "any ");
2544 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002545 }
2546 fprintf(output, "\n");
2547 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002548 fprintf(output, " ");
2549 if (type->minOccurs != 1)
2550 fprintf(output, "min: %d ", type->minOccurs);
2551 if (type->maxOccurs >= UNBOUNDED)
2552 fprintf(output, "max: unbounded\n");
2553 else if (type->maxOccurs != 1)
2554 fprintf(output, "max: %d\n", type->maxOccurs);
2555 else
2556 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002557 }
2558 if (type->annot != NULL)
2559 xmlSchemaAnnotDump(output, type->annot);
2560 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002561 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002562
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002563 fprintf(output, " subtypes: ");
2564 while (sub != NULL) {
2565 fprintf(output, "%s ", sub->name);
2566 sub = sub->next;
2567 }
2568 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002569 }
2570
2571}
2572
2573/**
2574 * xmlSchemaDump:
2575 * @output: the file output
2576 * @schema: a schema structure
2577 *
2578 * Dump a Schema structure.
2579 */
2580void
2581xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2582{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002583 if (output == NULL)
2584 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002585 if (schema == NULL) {
2586 fprintf(output, "Schemas: NULL\n");
2587 return;
2588 }
2589 fprintf(output, "Schemas: ");
2590 if (schema->name != NULL)
2591 fprintf(output, "%s, ", schema->name);
2592 else
2593 fprintf(output, "no name, ");
2594 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002595 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002596 else
2597 fprintf(output, "no target namespace");
2598 fprintf(output, "\n");
2599 if (schema->annot != NULL)
2600 xmlSchemaAnnotDump(output, schema->annot);
2601
2602 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2603 output);
2604 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002605 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002606}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002607#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002608
2609/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002610 * *
2611 * Utilities *
2612 * *
2613 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002614
Daniel Veillardc0826a72004-08-10 14:17:33 +00002615/**
2616 * xmlSchemaGetPropNode:
2617 * @node: the element node
2618 * @name: the name of the attribute
2619 *
2620 * Seeks an attribute with a name of @name in
2621 * no namespace.
2622 *
2623 * Returns the attribute or NULL if not present.
2624 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002625static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002626xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002627{
2628 xmlAttrPtr prop;
2629
Daniel Veillardc0826a72004-08-10 14:17:33 +00002630 if ((node == NULL) || (name == NULL))
2631 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002632 prop = node->properties;
2633 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002634 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2635 return(prop);
2636 prop = prop->next;
2637 }
2638 return (NULL);
2639}
2640
2641/**
2642 * xmlSchemaGetPropNodeNs:
2643 * @node: the element node
2644 * @uri: the uri
2645 * @name: the name of the attribute
2646 *
2647 * Seeks an attribute with a local name of @name and
2648 * a namespace URI of @uri.
2649 *
2650 * Returns the attribute or NULL if not present.
2651 */
2652static xmlAttrPtr
2653xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2654{
2655 xmlAttrPtr prop;
2656
2657 if ((node == NULL) || (name == NULL))
2658 return(NULL);
2659 prop = node->properties;
2660 while (prop != NULL) {
2661 if ((prop->ns != NULL) &&
2662 xmlStrEqual(prop->name, BAD_CAST name) &&
2663 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002664 return(prop);
2665 prop = prop->next;
2666 }
2667 return (NULL);
2668}
2669
2670static const xmlChar *
2671xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2672{
2673 xmlChar *val;
2674 const xmlChar *ret;
2675
2676 val = xmlNodeGetContent(node);
2677 if (val == NULL)
2678 return(NULL);
2679 ret = xmlDictLookup(ctxt->dict, val, -1);
2680 xmlFree(val);
2681 return(ret);
2682}
2683
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002684/**
2685 * xmlSchemaGetProp:
2686 * @ctxt: the parser context
2687 * @node: the node
2688 * @name: the property name
2689 *
2690 * Read a attribute value and internalize the string
2691 *
2692 * Returns the string or NULL if not present.
2693 */
2694static const xmlChar *
2695xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2696 const char *name)
2697{
2698 xmlChar *val;
2699 const xmlChar *ret;
2700
2701 val = xmlGetProp(node, BAD_CAST name);
2702 if (val == NULL)
2703 return(NULL);
2704 ret = xmlDictLookup(ctxt->dict, val, -1);
2705 xmlFree(val);
2706 return(ret);
2707}
2708
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002709/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002710 * *
2711 * Parsing functions *
2712 * *
2713 ************************************************************************/
2714
2715/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002716 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002717 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002718 * @name: the element name
2719 * @ns: the element namespace
2720 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002721 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002722 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002723 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002724 */
2725static xmlSchemaElementPtr
2726xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002727 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002728{
2729 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002730
2731 if ((name == NULL) || (schema == NULL))
2732 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002733
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002734 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002735 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002736 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002737 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002738 } else
2739 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002740 /*
2741 * This one was removed, since top level element declarations have
2742 * the target namespace specified in targetNamespace of the <schema>
2743 * information element, even if elementFormDefault is "unqualified".
2744 */
2745
2746 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002747 if (xmlStrEqual(namespace, schema->targetNamespace))
2748 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2749 else
2750 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002751 if ((ret != NULL) &&
2752 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002753 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002754 }
William M. Bracke7091952004-05-11 15:09:58 +00002755 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002756
William M. Brack2f2a6632004-08-20 23:09:47 +00002757 /*
2758 * Removed since imported components will be hold by the main schema only.
2759 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002760 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002761 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002762 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002763 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002764 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002765 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002766 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2767 return (ret);
2768 } else
2769 ret = NULL;
2770 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002771 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002772#ifdef DEBUG
2773 if (ret == NULL) {
2774 if (namespace == NULL)
2775 fprintf(stderr, "Unable to lookup type %s", name);
2776 else
2777 fprintf(stderr, "Unable to lookup type %s:%s", name,
2778 namespace);
2779 }
2780#endif
2781 return (ret);
2782}
2783
2784/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002785 * xmlSchemaGetType:
2786 * @schema: the schemas context
2787 * @name: the type name
2788 * @ns: the type namespace
2789 *
2790 * Lookup a type in the schemas or the predefined types
2791 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002792 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002793 */
2794static xmlSchemaTypePtr
2795xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002796 const xmlChar * namespace)
2797{
Daniel Veillard4255d502002-04-16 15:50:10 +00002798 xmlSchemaTypePtr ret;
2799
2800 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002801 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002802 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002803 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002804 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002805 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002806 }
2807 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002808 if (ret != NULL)
2809 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002810 /*
2811 * Removed, since the imported components will be grafted on the
2812 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002813 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002814 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002815 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002816 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002817 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002818 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002819 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2820 return (ret);
2821 } else
2822 ret = NULL;
2823 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002824 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002825#ifdef DEBUG
2826 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002827 if (namespace == NULL)
2828 fprintf(stderr, "Unable to lookup type %s", name);
2829 else
2830 fprintf(stderr, "Unable to lookup type %s:%s", name,
2831 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002832 }
2833#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002834 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002835}
2836
Daniel Veillard3646d642004-06-02 19:19:14 +00002837/**
2838 * xmlSchemaGetAttribute:
2839 * @schema: the context of the schema
2840 * @name: the name of the attribute
2841 * @ns: the target namespace of the attribute
2842 *
2843 * Lookup a an attribute in the schema or imported schemas
2844 *
2845 * Returns the attribute declaration or NULL if not found.
2846 */
2847static xmlSchemaAttributePtr
2848xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2849 const xmlChar * namespace)
2850{
2851 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002852
2853 if ((name == NULL) || (schema == NULL))
2854 return (NULL);
2855
2856
2857 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2858 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2859 return (ret);
2860 else
2861 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002862 /*
2863 * Removed, since imported components will be hold by the main schema only.
2864 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002865 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002866 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002867 else
2868 import = xmlHashLookup(schema->schemasImports, namespace);
2869 if (import != NULL) {
2870 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2871 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2872 return (ret);
2873 } else
2874 ret = NULL;
2875 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002876 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002877#ifdef DEBUG
2878 if (ret == NULL) {
2879 if (namespace == NULL)
2880 fprintf(stderr, "Unable to lookup attribute %s", name);
2881 else
2882 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2883 namespace);
2884 }
2885#endif
2886 return (ret);
2887}
2888
2889/**
2890 * xmlSchemaGetAttributeGroup:
2891 * @schema: the context of the schema
2892 * @name: the name of the attribute group
2893 * @ns: the target namespace of the attribute group
2894 *
2895 * Lookup a an attribute group in the schema or imported schemas
2896 *
2897 * Returns the attribute group definition or NULL if not found.
2898 */
2899static xmlSchemaAttributeGroupPtr
2900xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2901 const xmlChar * namespace)
2902{
2903 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002904
2905 if ((name == NULL) || (schema == NULL))
2906 return (NULL);
2907
2908
2909 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2910 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2911 return (ret);
2912 else
2913 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002914 /*
2915 * Removed since imported components will be hold by the main schema only.
2916 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002917 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002918 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002919 else
2920 import = xmlHashLookup(schema->schemasImports, namespace);
2921 if (import != NULL) {
2922 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2923 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2924 return (ret);
2925 else
2926 ret = NULL;
2927 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002928 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002929#ifdef DEBUG
2930 if (ret == NULL) {
2931 if (namespace == NULL)
2932 fprintf(stderr, "Unable to lookup attribute group %s", name);
2933 else
2934 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2935 namespace);
2936 }
2937#endif
2938 return (ret);
2939}
2940
2941/**
2942 * xmlSchemaGetGroup:
2943 * @schema: the context of the schema
2944 * @name: the name of the group
2945 * @ns: the target namespace of the group
2946 *
2947 * Lookup a group in the schema or imported schemas
2948 *
2949 * Returns the group definition or NULL if not found.
2950 */
2951static xmlSchemaTypePtr
2952xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2953 const xmlChar * namespace)
2954{
2955 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002956
2957 if ((name == NULL) || (schema == NULL))
2958 return (NULL);
2959
2960
2961 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2962 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2963 return (ret);
2964 else
2965 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002966 /*
2967 * Removed since imported components will be hold by the main schema only.
2968 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002969 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002970 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002971 else
2972 import = xmlHashLookup(schema->schemasImports, namespace);
2973 if (import != NULL) {
2974 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2975 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2976 return (ret);
2977 else
2978 ret = NULL;
2979 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002980 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002981#ifdef DEBUG
2982 if (ret == NULL) {
2983 if (namespace == NULL)
2984 fprintf(stderr, "Unable to lookup group %s", name);
2985 else
2986 fprintf(stderr, "Unable to lookup group %s:%s", name,
2987 namespace);
2988 }
2989#endif
2990 return (ret);
2991}
2992
Daniel Veillard4255d502002-04-16 15:50:10 +00002993/************************************************************************
2994 * *
2995 * Parsing functions *
2996 * *
2997 ************************************************************************/
2998
2999#define IS_BLANK_NODE(n) \
3000 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3001
3002/**
3003 * xmlSchemaIsBlank:
3004 * @str: a string
3005 *
3006 * Check if a string is ignorable
3007 *
3008 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3009 */
3010static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003011xmlSchemaIsBlank(xmlChar * str)
3012{
Daniel Veillard4255d502002-04-16 15:50:10 +00003013 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003014 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003015 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003016 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003017 return (0);
3018 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003020 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003021}
3022
3023/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003024 * xmlSchemaAddAssembledItem:
3025 * @ctxt: a schema parser context
3026 * @schema: the schema being built
3027 * @item: the item
3028 *
3029 * Add a item to the schema's list of current items.
3030 * This is used if the schema was already constructed and
3031 * new schemata need to be added to it.
3032 * *WARNING* this interface is highly subject to change.
3033 *
3034 * Returns 0 if suceeds and -1 if an internal error occurs.
3035 */
3036static int
3037xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3038 xmlSchemaTypePtr item)
3039{
3040 static int growSize = 100;
3041 xmlSchemaAssemblePtr ass;
3042
3043 ass = ctxt->assemble;
3044 if (ass->sizeItems < 0) {
3045 /* If disabled. */
3046 return (0);
3047 }
3048 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003049 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003050 if (ass->items == NULL) {
3051 xmlSchemaPErrMemory(ctxt,
3052 "allocating new item buffer", NULL);
3053 return (-1);
3054 }
3055 ass->sizeItems = growSize;
3056 } else if (ass->sizeItems <= ass->nbItems) {
3057 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003058 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003059 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3060 if (ass->items == NULL) {
3061 xmlSchemaPErrMemory(ctxt,
3062 "growing item buffer", NULL);
3063 ass->sizeItems = 0;
3064 return (-1);
3065 }
3066 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003067 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003068 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3069 return (0);
3070}
3071
3072/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003073 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003074 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003075 * @schema: the schema being built
3076 * @name: the item name
3077 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003078 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003079 * *WARNING* this interface is highly subject to change
3080 *
3081 * Returns the new struture or NULL in case of error
3082 */
3083static xmlSchemaNotationPtr
3084xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003085 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003086{
3087 xmlSchemaNotationPtr ret = NULL;
3088 int val;
3089
3090 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3091 return (NULL);
3092
3093 if (schema->notaDecl == NULL)
3094 schema->notaDecl = xmlHashCreate(10);
3095 if (schema->notaDecl == NULL)
3096 return (NULL);
3097
3098 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3099 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003100 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003101 return (NULL);
3102 }
3103 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003104 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003105 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3106 ret);
3107 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003108 /*
3109 * TODO: This should never happen, since a unique name will be computed.
3110 * If it fails, then an other internal error must have occured.
3111 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003112 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3113 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003114 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003115 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003116 xmlFree(ret);
3117 return (NULL);
3118 }
3119 return (ret);
3120}
3121
3122
3123/**
3124 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003125 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003126 * @schema: the schema being built
3127 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003128 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003129 *
3130 * Add an XML schema Attrribute declaration
3131 * *WARNING* this interface is highly subject to change
3132 *
3133 * Returns the new struture or NULL in case of error
3134 */
3135static xmlSchemaAttributePtr
3136xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003137 const xmlChar * name, const xmlChar * namespace,
3138 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003139{
3140 xmlSchemaAttributePtr ret = NULL;
3141 int val;
3142
3143 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3144 return (NULL);
3145
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003146#ifdef DEBUG
3147 fprintf(stderr, "Adding attribute %s\n", name);
3148 if (namespace != NULL)
3149 fprintf(stderr, " target namespace %s\n", namespace);
3150#endif
3151
Daniel Veillard4255d502002-04-16 15:50:10 +00003152 if (schema->attrDecl == NULL)
3153 schema->attrDecl = xmlHashCreate(10);
3154 if (schema->attrDecl == NULL)
3155 return (NULL);
3156
3157 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3158 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003159 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003160 return (NULL);
3161 }
3162 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003163 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003164 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003165 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003166 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003167 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003168 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003169 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003170 NULL, NULL, node,
3171 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003172 xmlFree(ret);
3173 return (NULL);
3174 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003175 if (ctxt->assemble != NULL)
3176 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 return (ret);
3178}
3179
3180/**
3181 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003182 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003183 * @schema: the schema being built
3184 * @name: the item name
3185 *
3186 * Add an XML schema Attrribute Group declaration
3187 *
3188 * Returns the new struture or NULL in case of error
3189 */
3190static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003191xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003192 xmlSchemaPtr schema, const xmlChar * name,
3193 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003194{
3195 xmlSchemaAttributeGroupPtr ret = NULL;
3196 int val;
3197
3198 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3199 return (NULL);
3200
3201 if (schema->attrgrpDecl == NULL)
3202 schema->attrgrpDecl = xmlHashCreate(10);
3203 if (schema->attrgrpDecl == NULL)
3204 return (NULL);
3205
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003206 ret =
3207 (xmlSchemaAttributeGroupPtr)
3208 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003209 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003210 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 return (NULL);
3212 }
3213 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003214 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003215 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003216 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003217 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003218 xmlSchemaPCustomErr(ctxt,
3219 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3220 NULL, NULL, node,
3221 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003222 xmlFree(ret);
3223 return (NULL);
3224 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003225 if (ctxt->assemble != NULL)
3226 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 return (ret);
3228}
3229
3230/**
3231 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003232 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003233 * @schema: the schema being built
3234 * @name: the type name
3235 * @namespace: the type namespace
3236 *
3237 * Add an XML schema Element declaration
3238 * *WARNING* this interface is highly subject to change
3239 *
3240 * Returns the new struture or NULL in case of error
3241 */
3242static xmlSchemaElementPtr
3243xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003244 const xmlChar * name, const xmlChar * namespace,
3245 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003246{
3247 xmlSchemaElementPtr ret = NULL;
3248 int val;
3249
3250 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3251 return (NULL);
3252
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003253#ifdef DEBUG
3254 fprintf(stderr, "Adding element %s\n", name);
3255 if (namespace != NULL)
3256 fprintf(stderr, " target namespace %s\n", namespace);
3257#endif
3258
Daniel Veillard4255d502002-04-16 15:50:10 +00003259 if (schema->elemDecl == NULL)
3260 schema->elemDecl = xmlHashCreate(10);
3261 if (schema->elemDecl == NULL)
3262 return (NULL);
3263
3264 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3265 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003266 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003267 return (NULL);
3268 }
3269 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003270 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003271 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003272 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003273 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003274 if (topLevel) {
3275 xmlSchemaPCustomErr(ctxt,
3276 XML_SCHEMAP_REDEFINED_ELEMENT,
3277 NULL, NULL, node,
3278 "A global element declaration with the name '%s' does "
3279 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003280 xmlFree(ret);
3281 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003282 } else {
3283 char buf[30];
3284
3285 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3286 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3287 namespace, ret);
3288 if (val != 0) {
3289 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003290 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003291 NULL, NULL, node,
3292 "Internal error: xmlSchemaAddElement, "
3293 "a dublicate element declaration with the name '%s' "
3294 "could not be added to the hash.", name);
3295 xmlFree(ret);
3296 return (NULL);
3297 }
3298 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003299
Daniel Veillard4255d502002-04-16 15:50:10 +00003300 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003301 if (ctxt->assemble != NULL)
3302 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003303 return (ret);
3304}
3305
3306/**
3307 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003308 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003309 * @schema: the schema being built
3310 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003311 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003312 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003313 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003314 * *WARNING* this interface is highly subject to change
3315 *
3316 * Returns the new struture or NULL in case of error
3317 */
3318static xmlSchemaTypePtr
3319xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003320 const xmlChar * name, const xmlChar * namespace,
3321 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003322{
3323 xmlSchemaTypePtr ret = NULL;
3324 int val;
3325
3326 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3327 return (NULL);
3328
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003329#ifdef DEBUG
3330 fprintf(stderr, "Adding type %s\n", name);
3331 if (namespace != NULL)
3332 fprintf(stderr, " target namespace %s\n", namespace);
3333#endif
3334
Daniel Veillard4255d502002-04-16 15:50:10 +00003335 if (schema->typeDecl == NULL)
3336 schema->typeDecl = xmlHashCreate(10);
3337 if (schema->typeDecl == NULL)
3338 return (NULL);
3339
3340 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3341 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003342 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003343 return (NULL);
3344 }
3345 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003346 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003347 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003348 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003349 if (val != 0) {
3350 if (ctxt->includes == 0) {
3351 xmlSchemaPCustomErr(ctxt,
3352 XML_SCHEMAP_REDEFINED_TYPE,
3353 NULL, NULL, node,
3354 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003355 xmlFree(ret);
3356 return (NULL);
3357 } else {
3358 xmlSchemaTypePtr prev;
3359
3360 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3361 if (prev == NULL) {
3362 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003363 XML_ERR_INTERNAL_ERROR,
3364 "Internal error: xmlSchemaAddType, on type "
3365 "'%s'.\n",
3366 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003367 xmlFree(ret);
3368 return (NULL);
3369 }
3370 ret->redef = prev->redef;
3371 prev->redef = ret;
3372 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003373 }
3374 ret->minOccurs = 1;
3375 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003376 ret->attributeUses = NULL;
3377 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003378 if (ctxt->assemble != NULL)
3379 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003380 return (ret);
3381}
3382
3383/**
3384 * xmlSchemaAddGroup:
3385 * @ctxt: a schema validation context
3386 * @schema: the schema being built
3387 * @name: the group name
3388 *
3389 * Add an XML schema Group definition
3390 *
3391 * Returns the new struture or NULL in case of error
3392 */
3393static xmlSchemaTypePtr
3394xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003395 const xmlChar *name, const xmlChar *namespaceName,
3396 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003397{
3398 xmlSchemaTypePtr ret = NULL;
3399 int val;
3400
3401 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3402 return (NULL);
3403
3404 if (schema->groupDecl == NULL)
3405 schema->groupDecl = xmlHashCreate(10);
3406 if (schema->groupDecl == NULL)
3407 return (NULL);
3408
3409 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3410 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003411 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003412 return (NULL);
3413 }
3414 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003415 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003416 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003417 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003418 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003419 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003420 xmlSchemaPCustomErr(ctxt,
3421 XML_SCHEMAP_REDEFINED_GROUP,
3422 NULL, NULL, node,
3423 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003424 xmlFree(ret);
3425 return (NULL);
3426 }
3427 ret->minOccurs = 1;
3428 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003429 if (ctxt->assemble != NULL)
3430 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003431 return (ret);
3432}
3433
Daniel Veillard3646d642004-06-02 19:19:14 +00003434/**
3435 * xmlSchemaNewWildcardNs:
3436 * @ctxt: a schema validation context
3437 *
3438 * Creates a new wildcard namespace constraint.
3439 *
3440 * Returns the new struture or NULL in case of error
3441 */
3442static xmlSchemaWildcardNsPtr
3443xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3444{
3445 xmlSchemaWildcardNsPtr ret;
3446
3447 ret = (xmlSchemaWildcardNsPtr)
3448 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3449 if (ret == NULL) {
3450 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3451 return (NULL);
3452 }
3453 ret->value = NULL;
3454 ret->next = NULL;
3455 return (ret);
3456}
3457
3458/**
3459 * xmlSchemaAddWildcard:
3460 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003461 * Adds a wildcard. It corresponds to a
3462 * xsd:anyAttribute and is used as storage for namespace
3463 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003464 *
3465 * Returns the new struture or NULL in case of error
3466 */
3467static xmlSchemaWildcardPtr
3468xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3469{
3470 xmlSchemaWildcardPtr ret = NULL;
3471
3472 if (ctxt == NULL)
3473 return (NULL);
3474
3475 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3476 if (ret == NULL) {
3477 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3478 return (NULL);
3479 }
3480 memset(ret, 0, sizeof(xmlSchemaWildcard));
3481 ret->minOccurs = 1;
3482 ret->maxOccurs = 1;
3483
3484 return (ret);
3485}
3486
Daniel Veillard4255d502002-04-16 15:50:10 +00003487/************************************************************************
3488 * *
3489 * Utilities for parsing *
3490 * *
3491 ************************************************************************/
3492
3493/**
3494 * xmlGetQNameProp:
3495 * @ctxt: a schema validation context
3496 * @node: a subtree containing XML Schema informations
3497 * @name: the attribute name
3498 * @namespace: the result namespace if any
3499 *
3500 * Extract a QName Attribute value
3501 *
3502 * Returns the NCName or NULL if not found, and also update @namespace
3503 * with the namespace URI
3504 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003505static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003506xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003507 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003508{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003509 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003510 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003511 const xmlChar *ret, *prefix;
3512 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003513 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003514
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003515 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003516 attr = xmlSchemaGetPropNode(node, name);
3517 if (attr == NULL)
3518 return (NULL);
3519 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003520
Daniel Veillard4255d502002-04-16 15:50:10 +00003521 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003522 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003523
Daniel Veillardba0153a2004-04-01 10:42:31 +00003524 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003525 ns = xmlSearchNs(node->doc, node, 0);
3526 if (ns) {
3527 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3528 return (val);
3529 }
3530 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003531 ret = xmlSplitQName3(val, &len);
3532 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003533 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003534 }
3535 ret = xmlDictLookup(ctxt->dict, ret, -1);
3536 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003537
3538 ns = xmlSearchNs(node->doc, node, prefix);
3539 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003540 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3541 NULL, NULL, (xmlNodePtr) attr,
3542 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003543 "The QName value '%s' has no corresponding namespace "
3544 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003545 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003546 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003547 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003548 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003549}
3550
3551/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003552 * xmlSchemaPValAttrNodeQNameValue:
3553 * @ctxt: a schema parser context
3554 * @schema: the schema context
3555 * @ownerDes: the designation of the parent element
3556 * @ownerItem: the parent as a schema object
3557 * @value: the QName value
3558 * @local: the resulting local part if found, the attribute value otherwise
3559 * @uri: the resulting namespace URI if found
3560 *
3561 * Extracts the local name and the URI of a QName value and validates it.
3562 * This one is intended to be used on attribute values that
3563 * should resolve to schema components.
3564 *
3565 * Returns 0, in case the QName is valid, a positive error code
3566 * if not valid and -1 if an internal error occurs.
3567 */
3568static int
3569xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3570 xmlSchemaPtr schema,
3571 xmlChar **ownerDes,
3572 xmlSchemaTypePtr ownerItem,
3573 xmlAttrPtr attr,
3574 const xmlChar *value,
3575 const xmlChar **uri,
3576 const xmlChar **prefix,
3577 const xmlChar **local)
3578{
3579 const xmlChar *pref;
3580 xmlNsPtr ns;
3581 int len, ret;
3582
3583 *uri = NULL;
3584 *local = NULL;
3585 if (prefix != 0)
3586 *prefix = NULL;
3587 ret = xmlValidateQName(value, 1);
3588 if (ret > 0) {
3589 xmlSchemaPSimpleTypeErr(ctxt,
3590 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3591 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003592 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3593 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003594 NULL, NULL, NULL);
3595 *local = value;
3596 return (ctxt->err);
3597 } else if (ret < 0)
3598 return (-1);
3599
3600 if (!strchr((char *) value, ':')) {
3601 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3602 if (ns)
3603 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3604 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3605 /*
3606 * This one takes care of included schemas with no
3607 * target namespace.
3608 */
3609 *uri = schema->targetNamespace;
3610 }
3611 *local = value;
3612 return (0);
3613 }
3614 /*
3615 * At this point xmlSplitQName3 has to return a local name.
3616 */
3617 *local = xmlSplitQName3(value, &len);
3618 *local = xmlDictLookup(ctxt->dict, *local, -1);
3619 pref = xmlDictLookup(ctxt->dict, value, len);
3620 if (prefix != 0)
3621 *prefix = pref;
3622 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3623 if (ns == NULL) {
3624 xmlSchemaPSimpleTypeErr(ctxt,
3625 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3626 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003627 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3628 "The QName value '%s' has no corresponding namespace "
3629 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003630 return (ctxt->err);
3631 } else {
3632 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3633 }
3634 return (0);
3635}
3636
3637/**
3638 * xmlSchemaPValAttrNodeQName:
3639 * @ctxt: a schema parser context
3640 * @schema: the schema context
3641 * @ownerDes: the designation of the owner element
3642 * @ownerItem: the owner as a schema object
3643 * @attr: the attribute node
3644 * @local: the resulting local part if found, the attribute value otherwise
3645 * @uri: the resulting namespace URI if found
3646 *
3647 * Extracts and validates the QName of an attribute value.
3648 * This one is intended to be used on attribute values that
3649 * should resolve to schema components.
3650 *
3651 * Returns 0, in case the QName is valid, a positive error code
3652 * if not valid and -1 if an internal error occurs.
3653 */
3654static int
3655xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3656 xmlSchemaPtr schema,
3657 xmlChar **ownerDes,
3658 xmlSchemaTypePtr ownerItem,
3659 xmlAttrPtr attr,
3660 const xmlChar **uri,
3661 const xmlChar **prefix,
3662 const xmlChar **local)
3663{
3664 const xmlChar *value;
3665
3666 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3667 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3668 ownerDes, ownerItem, attr, value, uri, prefix, local));
3669}
3670
3671/**
3672 * xmlSchemaPValAttrQName:
3673 * @ctxt: a schema parser context
3674 * @schema: the schema context
3675 * @ownerDes: the designation of the parent element
3676 * @ownerItem: the owner as a schema object
3677 * @ownerElem: the parent node of the attribute
3678 * @name: the name of the attribute
3679 * @local: the resulting local part if found, the attribute value otherwise
3680 * @uri: the resulting namespace URI if found
3681 *
3682 * Extracts and validates the QName of an attribute value.
3683 *
3684 * Returns 0, in case the QName is valid, a positive error code
3685 * if not valid and -1 if an internal error occurs.
3686 */
3687static int
3688xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3689 xmlSchemaPtr schema,
3690 xmlChar **ownerDes,
3691 xmlSchemaTypePtr ownerItem,
3692 xmlNodePtr ownerElem,
3693 const char *name,
3694 const xmlChar **uri,
3695 const xmlChar **prefix,
3696 const xmlChar **local)
3697{
3698 xmlAttrPtr attr;
3699
3700 attr = xmlSchemaGetPropNode(ownerElem, name);
3701 if (attr == NULL) {
3702 *local = NULL;
3703 *uri = NULL;
3704 return (0);
3705 }
3706 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3707 ownerDes, ownerItem, attr, uri, prefix, local));
3708}
3709
3710/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003711 * xmlGetMaxOccurs:
3712 * @ctxt: a schema validation context
3713 * @node: a subtree containing XML Schema informations
3714 *
3715 * Get the maxOccurs property
3716 *
3717 * Returns the default if not found, or the value
3718 */
3719static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003720xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3721 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003722{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003723 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003724 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003725 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003726
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003727 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3728 if (attr == NULL)
3729 return (def);
3730 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003731
3732 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003733 if (max != UNBOUNDED) {
3734 xmlSchemaPSimpleTypeErr(ctxt,
3735 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3736 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3737 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3738 val, NULL, NULL, NULL);
3739 return (def);
3740 } else
3741 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003742 }
3743
3744 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003745 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003746 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003747 if (*cur == 0) {
3748 xmlSchemaPSimpleTypeErr(ctxt,
3749 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3750 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3751 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3752 val, NULL, NULL, NULL);
3753 return (def);
3754 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003755 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003756 ret = ret * 10 + (*cur - '0');
3757 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003758 }
William M. Brack76e95df2003-10-18 16:20:14 +00003759 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003760 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003761 /*
3762 * TODO: Restrict the maximal value to Integer.
3763 */
3764 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3765 xmlSchemaPSimpleTypeErr(ctxt,
3766 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3767 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3768 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3769 val, NULL, NULL, NULL);
3770 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003771 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003772 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003773}
3774
3775/**
3776 * xmlGetMinOccurs:
3777 * @ctxt: a schema validation context
3778 * @node: a subtree containing XML Schema informations
3779 *
3780 * Get the minOccurs property
3781 *
3782 * Returns the default if not found, or the value
3783 */
3784static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003785xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3786 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003787{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003788 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003789 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003790 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003791
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003792 attr = xmlSchemaGetPropNode(node, "minOccurs");
3793 if (attr == NULL)
3794 return (def);
3795 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003796 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003797 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003798 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003799 if (*cur == 0) {
3800 xmlSchemaPSimpleTypeErr(ctxt,
3801 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3802 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3803 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3804 val, NULL, NULL, NULL);
3805 return (def);
3806 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003807 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003808 ret = ret * 10 + (*cur - '0');
3809 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003810 }
William M. Brack76e95df2003-10-18 16:20:14 +00003811 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003812 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003813 /*
3814 * TODO: Restrict the maximal value to Integer.
3815 */
3816 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3817 xmlSchemaPSimpleTypeErr(ctxt,
3818 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3819 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3820 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3821 val, NULL, NULL, NULL);
3822 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003823 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003824 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003825}
3826
3827/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003828 * xmlSchemaPGetBoolNodeValue:
3829 * @ctxt: a schema validation context
3830 * @ownerDes: owner designation
3831 * @ownerItem: the owner as a schema item
3832 * @node: the node holding the value
3833 *
3834 * Converts a boolean string value into 1 or 0.
3835 *
3836 * Returns 0 or 1.
3837 */
3838static int
3839xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3840 xmlChar **ownerDes,
3841 xmlSchemaTypePtr ownerItem,
3842 xmlNodePtr node)
3843{
3844 xmlChar *value = NULL;
3845 int res = 0;
3846
3847 value = xmlNodeGetContent(node);
3848 /*
3849 * 3.2.2.1 Lexical representation
3850 * An instance of a datatype that is defined as ·boolean·
3851 * can have the following legal literals {true, false, 1, 0}.
3852 */
3853 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3854 res = 1;
3855 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3856 res = 0;
3857 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3858 res = 1;
3859 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3860 res = 0;
3861 else {
3862 xmlSchemaPSimpleTypeErr(ctxt,
3863 XML_SCHEMAP_INVALID_BOOLEAN,
3864 ownerDes, ownerItem, node,
3865 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3866 "(1 | 0 | true | false)", BAD_CAST value,
3867 NULL, NULL, NULL);
3868 }
3869 if (value != NULL)
3870 xmlFree(value);
3871 return (res);
3872}
3873
3874/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003875 * xmlGetBooleanProp:
3876 * @ctxt: a schema validation context
3877 * @node: a subtree containing XML Schema informations
3878 * @name: the attribute name
3879 * @def: the default value
3880 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003881 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003882 *
3883 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003884 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003885 */
3886static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003887xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3888 xmlChar **ownerDes,
3889 xmlSchemaTypePtr ownerItem,
3890 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003891 const char *name, int def)
3892{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003893 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003894
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003895 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003896 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003897 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003898 /*
3899 * 3.2.2.1 Lexical representation
3900 * An instance of a datatype that is defined as ·boolean·
3901 * can have the following legal literals {true, false, 1, 0}.
3902 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003903 if (xmlStrEqual(val, BAD_CAST "true"))
3904 def = 1;
3905 else if (xmlStrEqual(val, BAD_CAST "false"))
3906 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003907 else if (xmlStrEqual(val, BAD_CAST "1"))
3908 def = 1;
3909 else if (xmlStrEqual(val, BAD_CAST "0"))
3910 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003911 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003912 xmlSchemaPSimpleTypeErr(ctxt,
3913 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003914 ownerDes, ownerItem, node,
3915 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3916 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003917 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003918 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003919}
3920
3921/************************************************************************
3922 * *
3923 * Shema extraction from an Infoset *
3924 * *
3925 ************************************************************************/
3926static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3927 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003928 xmlNodePtr node,
3929 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003930static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3931 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003932 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003933 xmlNodePtr node,
3934 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003935static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3936 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003938 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003939static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3940 xmlSchemaPtr schema,
3941 xmlNodePtr node);
3942static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3943 xmlSchemaPtr schema,
3944 xmlNodePtr node);
3945static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3946 ctxt,
3947 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003948 xmlNodePtr node,
3949 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003950static xmlSchemaAttributeGroupPtr
3951xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003952 xmlSchemaPtr schema, xmlNodePtr node,
3953 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003954static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3955 xmlSchemaPtr schema,
3956 xmlNodePtr node);
3957static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3958 xmlSchemaPtr schema,
3959 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003960static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003961xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3962 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003963
3964/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003965 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003966 *
3967 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003968 * @ownerDes: the designation of the parent element
3969 * @ownerItem: the schema object owner if existent
3970 * @attr: the schema attribute node being validated
3971 * @value: the value
3972 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003973 *
3974 * Validates a value against the given built-in type.
3975 * This one is intended to be used internally for validation
3976 * of schema attribute values during parsing of the schema.
3977 *
3978 * Returns 0 if the value is valid, a positive error code
3979 * number otherwise and -1 in case of an internal or API error.
3980 */
3981static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003982xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3983 xmlChar **ownerDes,
3984 xmlSchemaTypePtr ownerItem,
3985 xmlAttrPtr attr,
3986 const xmlChar *value,
3987 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003988{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003989
Daniel Veillardc0826a72004-08-10 14:17:33 +00003990 int ret = 0;
3991
3992 /*
3993 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3994 * one is really meant to be used internally, so better not.
3995 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003996 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003997 return (-1);
3998 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3999 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004000 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004001 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004002 "type '%s' is not a built-in type.\n",
4003 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004004 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004005 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004006 switch (type->builtInType) {
4007 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004008 case XML_SCHEMAS_QNAME:
4009 case XML_SCHEMAS_ANYURI:
4010 case XML_SCHEMAS_TOKEN:
4011 case XML_SCHEMAS_LANGUAGE:
4012 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4013 break;
4014
4015 /*
4016 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004017 ret = xmlValidateNCName(value, 1);
4018 break;
4019 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004020 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004021 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004022 "Internal error: xmlSchemaPvalueAttrNode, use "
4023 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4024 "for extracting QName valueues instead.\n",
4025 NULL, NULL);
4026 return (-1);
4027 case XML_SCHEMAS_ANYURI:
4028 if (value != NULL) {
4029 xmlURIPtr uri = xmlParseURI((const char *) value);
4030 if (uri == NULL)
4031 ret = 1;
4032 else
4033 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004034 }
4035 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004036 case XML_SCHEMAS_TOKEN: {
4037 const xmlChar *cur = value;
4038
4039 if (IS_BLANK_CH(*cur)) {
4040 ret = 1;
4041 } else while (*cur != 0) {
4042 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4043 ret = 1;
4044 break;
4045 } else if (*cur == ' ') {
4046 cur++;
4047 if ((*cur == 0) || (*cur == ' ')) {
4048 ret = 1;
4049 break;
4050 }
4051 } else {
4052 cur++;
4053 }
4054 }
4055 }
4056 break;
4057 case XML_SCHEMAS_LANGUAGE:
4058 if (xmlCheckLanguageID(value) != 1)
4059 ret = 1;
4060 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004061 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004062 default: {
4063 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004064 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004065 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004066 "valueidation using the type '%s' is not implemented "
4067 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004068 type->name, NULL);
4069 return (-1);
4070 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004071 }
4072 /*
4073 * TODO: Should we use the S4S error codes instead?
4074 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004075 if (ret < 0) {
4076 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4077 XML_SCHEMAP_INTERNAL,
4078 "Internal error: xmlSchemaPValAttrNodeValue, "
4079 "failed to validate a schema attribute value.\n",
4080 NULL, NULL);
4081 return (-1);
4082 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004083 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4084 xmlSchemaPSimpleTypeErr(ctxt,
4085 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4086 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004087 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004088 NULL, NULL, NULL);
4089 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4090 } else {
4091 xmlSchemaPSimpleTypeErr(ctxt,
4092 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4093 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004094 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004095 NULL, NULL, NULL);
4096 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4097 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004098 }
4099 return (ret);
4100}
4101
4102/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004103 * xmlSchemaPValAttrNode:
4104 *
4105 * @ctxt: a schema parser context
4106 * @ownerDes: the designation of the parent element
4107 * @ownerItem: the schema object owner if existent
4108 * @attr: the schema attribute node being validated
4109 * @type: the built-in type to be validated against
4110 * @value: the resulting value if any
4111 *
4112 * Extracts and validates a value against the given built-in type.
4113 * This one is intended to be used internally for validation
4114 * of schema attribute values during parsing of the schema.
4115 *
4116 * Returns 0 if the value is valid, a positive error code
4117 * number otherwise and -1 in case of an internal or API error.
4118 */
4119static int
4120xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4121 xmlChar **ownerDes,
4122 xmlSchemaTypePtr ownerItem,
4123 xmlAttrPtr attr,
4124 xmlSchemaTypePtr type,
4125 const xmlChar **value)
4126{
4127 const xmlChar *val;
4128
4129 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4130 return (-1);
4131
4132 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4133 if (value != NULL)
4134 *value = val;
4135
4136 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4137 val, type));
4138}
4139
4140/**
4141 * xmlSchemaPValAttr:
4142 *
4143 * @ctxt: a schema parser context
4144 * @node: the element node of the attribute
4145 * @ownerDes: the designation of the parent element
4146 * @ownerItem: the schema object owner if existent
4147 * @ownerElem: the owner element node
4148 * @name: the name of the schema attribute node
4149 * @type: the built-in type to be validated against
4150 * @value: the resulting value if any
4151 *
4152 * Extracts and validates a value against the given built-in type.
4153 * This one is intended to be used internally for validation
4154 * of schema attribute values during parsing of the schema.
4155 *
4156 * Returns 0 if the value is valid, a positive error code
4157 * number otherwise and -1 in case of an internal or API error.
4158 */
4159static int
4160xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4161 xmlChar **ownerDes,
4162 xmlSchemaTypePtr ownerItem,
4163 xmlNodePtr ownerElem,
4164 const char *name,
4165 xmlSchemaTypePtr type,
4166 const xmlChar **value)
4167{
4168 xmlAttrPtr attr;
4169
4170 if ((ctxt == NULL) || (type == NULL)) {
4171 if (value != NULL)
4172 *value = NULL;
4173 return (-1);
4174 }
4175 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4176 if (value != NULL)
4177 *value = NULL;
4178 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004179 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004180 "Internal error: xmlSchemaPValAttr, the given "
4181 "type '%s' is not a built-in type.\n",
4182 type->name, NULL);
4183 return (-1);
4184 }
4185 attr = xmlSchemaGetPropNode(ownerElem, name);
4186 if (attr == NULL) {
4187 if (value != NULL)
4188 *value = NULL;
4189 return (0);
4190 }
4191 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4192 type, value));
4193}
4194/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004195 * xmlSchemaParseAttrDecls:
4196 * @ctxt: a schema validation context
4197 * @schema: the schema being built
4198 * @node: a subtree containing XML Schema informations
4199 * @type: the hosting type
4200 *
4201 * parse a XML schema attrDecls declaration corresponding to
4202 * <!ENTITY % attrDecls
4203 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4204 */
4205static xmlNodePtr
4206xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4207 xmlNodePtr child, xmlSchemaTypePtr type)
4208{
4209 xmlSchemaAttributePtr lastattr, attr;
4210
4211 lastattr = NULL;
4212 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004213 (IS_SCHEMA(child, "attributeGroup"))) {
4214 attr = NULL;
4215 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004216 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004217 } else if (IS_SCHEMA(child, "attributeGroup")) {
4218 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004219 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004220 }
4221 if (attr != NULL) {
4222 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004223 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4224 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4225 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004226 type->attributes = attr;
4227 lastattr = attr;
4228 } else {
4229 lastattr->next = attr;
4230 lastattr = attr;
4231 }
4232 }
4233 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004234 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004235 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004236}
4237
4238/**
4239 * xmlSchemaParseAnnotation:
4240 * @ctxt: a schema validation context
4241 * @schema: the schema being built
4242 * @node: a subtree containing XML Schema informations
4243 *
4244 * parse a XML schema Attrribute declaration
4245 * *WARNING* this interface is highly subject to change
4246 *
William M. Bracke7091952004-05-11 15:09:58 +00004247 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 * 1 in case of success.
4249 */
4250static xmlSchemaAnnotPtr
4251xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4252 xmlNodePtr node)
4253{
4254 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004255 xmlNodePtr child = NULL;
4256 xmlAttrPtr attr;
4257 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004258
Daniel Veillardc0826a72004-08-10 14:17:33 +00004259 /*
4260 * INFO: S4S completed.
4261 */
4262 /*
4263 * id = ID
4264 * {any attributes with non-schema namespace . . .}>
4265 * Content: (appinfo | documentation)*
4266 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004267 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4268 return (NULL);
4269 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004270 attr = node->properties;
4271 while (attr != NULL) {
4272 if (((attr->ns == NULL) &&
4273 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4274 ((attr->ns != NULL) &&
4275 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4276
4277 xmlSchemaPIllegalAttrErr(ctxt,
4278 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4279 NULL, NULL, attr);
4280 }
4281 attr = attr->next;
4282 }
4283 /* TODO: Check id. */
4284
4285 /*
4286 * And now for the children...
4287 */
4288 child = node->children;
4289 while (child != NULL) {
4290 if (IS_SCHEMA(child, "appinfo")) {
4291 /* TODO: make available the content of "appinfo". */
4292 /*
4293 * source = anyURI
4294 * {any attributes with non-schema namespace . . .}>
4295 * Content: ({any})*
4296 */
4297 attr = child->properties;
4298 while (attr != NULL) {
4299 if (((attr->ns == NULL) &&
4300 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4301 ((attr->ns != NULL) &&
4302 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004303
Daniel Veillardc0826a72004-08-10 14:17:33 +00004304 xmlSchemaPIllegalAttrErr(ctxt,
4305 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4306 NULL, NULL, attr);
4307 }
4308 attr = attr->next;
4309 }
4310 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4311 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4312 child = child->next;
4313 } else if (IS_SCHEMA(child, "documentation")) {
4314 /* TODO: make available the content of "documentation". */
4315 /*
4316 * source = anyURI
4317 * {any attributes with non-schema namespace . . .}>
4318 * Content: ({any})*
4319 */
4320 attr = child->properties;
4321 while (attr != NULL) {
4322 if (attr->ns == NULL) {
4323 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4324 xmlSchemaPIllegalAttrErr(ctxt,
4325 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4326 NULL, NULL, attr);
4327 }
4328 } else {
4329 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4330 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4331 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4332
4333 xmlSchemaPIllegalAttrErr(ctxt,
4334 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4335 NULL, NULL, attr);
4336 }
4337 }
4338 attr = attr->next;
4339 }
4340 /*
4341 * Attribute "xml:lang".
4342 */
4343 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4344 if (attr != NULL)
4345 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4346 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4347 child = child->next;
4348 } else {
4349 if (!barked)
4350 xmlSchemaPContentErr(ctxt,
4351 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4352 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4353 barked = 1;
4354 child = child->next;
4355 }
4356 }
4357
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 return (ret);
4359}
4360
4361/**
4362 * xmlSchemaParseFacet:
4363 * @ctxt: a schema validation context
4364 * @schema: the schema being built
4365 * @node: a subtree containing XML Schema informations
4366 *
4367 * parse a XML schema Facet declaration
4368 * *WARNING* this interface is highly subject to change
4369 *
4370 * Returns the new type structure or NULL in case of error
4371 */
4372static xmlSchemaFacetPtr
4373xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004374 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004375{
4376 xmlSchemaFacetPtr facet;
4377 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004378 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004379
4380 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4381 return (NULL);
4382
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004383 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004384 if (facet == NULL) {
4385 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4386 return (NULL);
4387 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004388 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004389 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004391 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4392 "Facet %s has no value\n", node->name, NULL);
4393 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004394 return (NULL);
4395 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004396 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004399 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004400 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004401 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004406 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004407 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004409 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004410 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004411 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004412 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004413 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004416 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004417 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4418 } else if (IS_SCHEMA(node, "minLength")) {
4419 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4420 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004421 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4422 "Unknown facet type %s\n", node->name, NULL);
4423 xmlSchemaFreeFacet(facet);
4424 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004425 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004426 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004427 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004428 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4429 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4430 const xmlChar *fixed;
4431
4432 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4433 if (fixed != NULL) {
4434 if (xmlStrEqual(fixed, BAD_CAST "true"))
4435 facet->fixed = 1;
4436 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004437 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004438 child = node->children;
4439
4440 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4442 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 }
4444 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004445 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4446 "Facet %s has unexpected child content\n",
4447 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 }
4449 return (facet);
4450}
4451
4452/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004453 * xmlSchemaParseWildcardNs:
4454 * @ctxt: a schema parser context
4455 * @wildc: the wildcard, already created
4456 * @node: a subtree containing XML Schema informations
4457 *
4458 * Parses the attribute "processContents" and "namespace"
4459 * of a xsd:anyAttribute and xsd:any.
4460 * *WARNING* this interface is highly subject to change
4461 *
4462 * Returns 0 if everything goes fine, a positive error code
4463 * if something is not valid and -1 if an internal error occurs.
4464 */
4465static int
4466xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4467 xmlSchemaPtr schema,
4468 xmlSchemaWildcardPtr wildc,
4469 xmlNodePtr node)
4470{
4471 const xmlChar *pc, *ns, *dictnsItem;
4472 int ret = 0;
4473 xmlChar *nsItem;
4474 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4475 xmlAttrPtr attr;
4476
4477 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4478 if ((pc == NULL)
4479 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4480 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4481 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4482 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4483 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4484 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4485 } else {
4486 xmlSchemaPSimpleTypeErr(ctxt,
4487 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4488 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004489 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004490 NULL, NULL, NULL);
4491 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4492 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4493 }
4494 /*
4495 * Build the namespace constraints.
4496 */
4497 attr = xmlSchemaGetPropNode(node, "namespace");
4498 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4499 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4500 wildc->any = 1;
4501 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4502 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4503 if (wildc->negNsSet == NULL) {
4504 return (-1);
4505 }
4506 wildc->negNsSet->value = schema->targetNamespace;
4507 } else {
4508 const xmlChar *end, *cur;
4509
4510 cur = ns;
4511 do {
4512 while (IS_BLANK_CH(*cur))
4513 cur++;
4514 end = cur;
4515 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4516 end++;
4517 if (end == cur)
4518 break;
4519 nsItem = xmlStrndup(cur, end - cur);
4520 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4521 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4522 xmlSchemaPSimpleTypeErr(ctxt,
4523 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4524 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004525 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004526 "((##any | ##other) | List of (anyURI | "
4527 "(##targetNamespace | ##local)))",
4528 nsItem, NULL, NULL, NULL);
4529 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4530 } else {
4531 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4532 dictnsItem = schema->targetNamespace;
4533 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4534 dictnsItem = NULL;
4535 } else {
4536 /*
4537 * Validate the item (anyURI).
4538 */
4539 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4540 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4541 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4542 }
4543 /*
4544 * Avoid dublicate namespaces.
4545 */
4546 tmp = wildc->nsSet;
4547 while (tmp != NULL) {
4548 if (dictnsItem == tmp->value)
4549 break;
4550 tmp = tmp->next;
4551 }
4552 if (tmp == NULL) {
4553 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4554 if (tmp == NULL) {
4555 xmlFree(nsItem);
4556 return (-1);
4557 }
4558 tmp->value = dictnsItem;
4559 tmp->next = NULL;
4560 if (wildc->nsSet == NULL)
4561 wildc->nsSet = tmp;
4562 else
4563 lastNs->next = tmp;
4564 lastNs = tmp;
4565 }
4566
4567 }
4568 xmlFree(nsItem);
4569 cur = end;
4570 } while (*cur != 0);
4571 }
4572 return (ret);
4573}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004574
4575static int
4576xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4577 xmlSchemaTypePtr item,
4578 xmlNodePtr node,
4579 int minOccurs,
4580 int maxOccurs) {
4581
4582 if (maxOccurs != UNBOUNDED) {
4583 /*
4584 * TODO: Maby we should better not create the particle,
4585 * if min/max is invalid, since it could confuse the build of the
4586 * content model.
4587 */
4588 /*
4589 * 3.9.6 Schema Component Constraint: Particle Correct
4590 *
4591 */
4592 if (maxOccurs < 1) {
4593 /*
4594 * 2.2 {max occurs} must be greater than or equal to 1.
4595 */
4596 xmlSchemaPCustomAttrErr(ctxt,
4597 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4598 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4599 "The value must be greater than or equal to 1");
4600 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4601 } else if (minOccurs > maxOccurs) {
4602 /*
4603 * 2.1 {min occurs} must not be greater than {max occurs}.
4604 */
4605 xmlSchemaPCustomAttrErr(ctxt,
4606 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4607 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4608 "The value must not be greater than the value of 'maxOccurs'");
4609 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4610 }
4611 }
4612 return (0);
4613}
4614
Daniel Veillardc0826a72004-08-10 14:17:33 +00004615/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004616 * xmlSchemaParseAny:
4617 * @ctxt: a schema validation context
4618 * @schema: the schema being built
4619 * @node: a subtree containing XML Schema informations
4620 *
4621 * parse a XML schema Any declaration
4622 * *WARNING* this interface is highly subject to change
4623 *
4624 * Returns the new type structure or NULL in case of error
4625 */
4626static xmlSchemaTypePtr
4627xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4628 xmlNodePtr node)
4629{
4630 xmlSchemaTypePtr type;
4631 xmlNodePtr child = NULL;
4632 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004633 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004634 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004635
4636 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4637 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004638 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4639 "(nonNegativeInteger | unbounded)");
4640 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4641 "nonNegativeInteger");
4642 if ((minOccurs == 0) && (maxOccurs == 0))
4643 return (NULL);
4644
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004645 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004646 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004647 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004648 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004649 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004650 type->type = XML_SCHEMA_TYPE_ANY;
4651
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004652 /*
4653 * TODO: Use a particle component here.
4654 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004655 wildc = xmlSchemaAddWildcard(ctxt);
4656 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004657 * Check min/max sanity.
4658 */
4659 type->maxOccurs = maxOccurs;
4660 type->minOccurs = minOccurs;
4661 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4662 node, type->minOccurs, type->maxOccurs);
4663 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004664 * This is not nice, since it is won't be used as a attribute wildcard,
4665 * but better than adding a field to the structure.
4666 */
4667 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004668 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004669 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004670 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004671 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4672 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004673 }
4674 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004675 xmlSchemaPErr2(ctxt, node, child,
4676 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4677 "Sequence %s has unexpected content\n", type->name,
4678 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004679 }
4680
4681 return (type);
4682}
4683
4684/**
4685 * xmlSchemaParseNotation:
4686 * @ctxt: a schema validation context
4687 * @schema: the schema being built
4688 * @node: a subtree containing XML Schema informations
4689 *
4690 * parse a XML schema Notation declaration
4691 *
4692 * Returns the new structure or NULL in case of error
4693 */
4694static xmlSchemaNotationPtr
4695xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004696 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004697{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004698 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004699 xmlSchemaNotationPtr ret;
4700 xmlNodePtr child = NULL;
4701
4702 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4703 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004704 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004705 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004706 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4707 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004708 return (NULL);
4709 }
4710 ret = xmlSchemaAddNotation(ctxt, schema, name);
4711 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004712 return (NULL);
4713 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004714 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004715 child = node->children;
4716 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004717 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4718 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004719 }
4720 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004721 xmlSchemaPErr2(ctxt, node, child,
4722 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4723 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004724 }
4725
4726 return (ret);
4727}
4728
4729/**
4730 * xmlSchemaParseAnyAttribute:
4731 * @ctxt: a schema validation context
4732 * @schema: the schema being built
4733 * @node: a subtree containing XML Schema informations
4734 *
4735 * parse a XML schema AnyAttrribute declaration
4736 * *WARNING* this interface is highly subject to change
4737 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004738 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004739 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004740static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004741xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4742 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004743{
Daniel Veillard3646d642004-06-02 19:19:14 +00004744 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004745 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004746 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004747
4748 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4749 return (NULL);
4750
Daniel Veillard3646d642004-06-02 19:19:14 +00004751 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004752 if (ret == NULL) {
4753 return (NULL);
4754 }
William M. Bracke7091952004-05-11 15:09:58 +00004755 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004756 /*
4757 * Check for illegal attributes.
4758 */
4759 attr = node->properties;
4760 while (attr != NULL) {
4761 if (attr->ns == NULL) {
4762 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4763 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4764 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4765 xmlSchemaPIllegalAttrErr(ctxt,
4766 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4767 NULL, NULL, attr);
4768 }
4769 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4770 xmlSchemaPIllegalAttrErr(ctxt,
4771 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4772 NULL, NULL, attr);
4773 }
4774 attr = attr->next;
4775 }
4776 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4777 /*
4778 * Parse the namespace list.
4779 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004780 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4781 xmlSchemaFreeWildcard(ret);
4782 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004783 }
4784 /*
4785 * And now for the children...
4786 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004787 child = node->children;
4788 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4790 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004791 }
4792 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004793 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004794 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4795 NULL, NULL, node, child,
4796 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004797 }
4798
4799 return (ret);
4800}
4801
4802
4803/**
4804 * xmlSchemaParseAttribute:
4805 * @ctxt: a schema validation context
4806 * @schema: the schema being built
4807 * @node: a subtree containing XML Schema informations
4808 *
4809 * parse a XML schema Attrribute declaration
4810 * *WARNING* this interface is highly subject to change
4811 *
William M. Bracke7091952004-05-11 15:09:58 +00004812 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004813 */
4814static xmlSchemaAttributePtr
4815xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004816 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004817{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004818 const xmlChar *name, *attrValue;
4819 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004820 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004821 xmlNodePtr child = NULL;
4822 xmlAttrPtr attr, nameAttr;
4823 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004824
4825 /*
4826 * Note that the w3c spec assumes the schema to be validated with schema
4827 * for schemas beforehand.
4828 *
4829 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004830 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004831
4832 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4833 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004834 attr = xmlSchemaGetPropNode(node, "ref");
4835 nameAttr = xmlSchemaGetPropNode(node, "name");
4836
4837 if ((attr == NULL) && (nameAttr == NULL)) {
4838 /*
4839 * 3.2.3 : 3.1
4840 * One of ref or name must be present, but not both
4841 */
4842 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4843 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4844 "One of the attributes 'ref' or 'name' must be present");
4845 return (NULL);
4846 }
4847 if ((topLevel) || (attr == NULL)) {
4848 if (nameAttr == NULL) {
4849 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4850 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4851 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004852 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004853 }
4854 } else
4855 isRef = 1;
4856
4857 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004858 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004859 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4860
4861 /*
4862 * Parse as attribute reference.
4863 */
4864 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4865 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4866 &refPrefix, &ref) != 0) {
4867 return (NULL);
4868 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004869 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004870 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004871 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004872 if (ret == NULL) {
4873 if (repName != NULL)
4874 xmlFree(repName);
4875 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004876 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004877 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4878 ret->node = node;
4879 ret->refNs = refNs;
4880 ret->refPrefix = refPrefix;
4881 ret->ref = ref;
4882 /*
4883 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4884 */
4885 if (nameAttr != NULL)
4886 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4887 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4888 "ref", "name");
4889 /*
4890 * Check for illegal attributes.
4891 */
4892 attr = node->properties;
4893 while (attr != NULL) {
4894 if (attr->ns == NULL) {
4895 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4896 xmlStrEqual(attr->name, BAD_CAST "form")) {
4897 /*
4898 * 3.2.3 : 3.2
4899 * If ref is present, then all of <simpleType>,
4900 * form and type must be absent.
4901 */
4902 xmlSchemaPIllegalAttrErr(ctxt,
4903 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4904 (xmlSchemaTypePtr) ret, attr);
4905 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4906 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4907 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4908 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4909 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4910 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4911 xmlSchemaPIllegalAttrErr(ctxt,
4912 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4913 &repName, (xmlSchemaTypePtr) ret, attr);
4914 }
4915 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4916 xmlSchemaPIllegalAttrErr(ctxt,
4917 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4918 &repName, (xmlSchemaTypePtr) ret, attr);
4919 }
4920 attr = attr->next;
4921 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004922 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004923 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004924
4925 /*
4926 * Parse as attribute declaration.
4927 */
4928 if (xmlSchemaPValAttrNode(ctxt,
4929 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4930 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4931 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004932 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004933 /*
4934 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4935 */
4936 /*
4937 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4938 */
4939 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4940 xmlSchemaPSimpleTypeErr(ctxt,
4941 XML_SCHEMAP_NO_XMLNS,
4942 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004943 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004944 "The value must not match 'xmlns'",
4945 NULL, NULL);
4946 if (repName != NULL)
4947 xmlFree(repName);
4948 return (NULL);
4949 }
4950 /*
4951 * Evaluate the target namespace
4952 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004953 if (topLevel) {
4954 ns = schema->targetNamespace;
4955 } else {
4956 attr = xmlSchemaGetPropNode(node, "form");
4957 if (attr != NULL) {
4958 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4959 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4960 ns = schema->targetNamespace;
4961 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4962 xmlSchemaPSimpleTypeErr(ctxt,
4963 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4964 &repName, NULL, (xmlNodePtr) attr,
4965 NULL, "(qualified | unqualified)",
4966 attrValue, NULL, NULL, NULL);
4967 }
4968 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4969 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004970 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004971 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004972 if (ret == NULL) {
4973 if (repName != NULL)
4974 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004975 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004976 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004977 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004978 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004979 if (topLevel)
4980 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4981 /*
4982 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4983 */
4984 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4985 xmlSchemaPCustomErr(ctxt,
4986 XML_SCHEMAP_NO_XSI,
4987 &repName, (xmlSchemaTypePtr) ret, node,
4988 "The target namespace must not match '%s'",
4989 xmlSchemaInstanceNs);
4990 }
4991 /*
4992 * Check for illegal attributes.
4993 */
4994 attr = node->properties;
4995 while (attr != NULL) {
4996 if (attr->ns == NULL) {
4997 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4998 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4999 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5000 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5001 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5002 if ((topLevel) ||
5003 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5004 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5005 xmlSchemaPIllegalAttrErr(ctxt,
5006 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5007 &repName, (xmlSchemaTypePtr) ret, attr);
5008 }
5009 }
5010 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5011 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5012 &repName, (xmlSchemaTypePtr) ret, attr);
5013 }
5014 attr = attr->next;
5015 }
5016 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5017 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005018 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005019 /* TODO: Check ID. */
5020 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005021 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005022 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005023 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005024 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5025 if (ret->defValue != NULL)
5026 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5027 /*
5028 * Attribute "default".
5029 */
5030 attr = xmlSchemaGetPropNode(node, "default");
5031 if (attr != NULL) {
5032 /*
5033 * 3.2.3 : 1
5034 * default and fixed must not both be present.
5035 */
5036 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5037 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5038 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5039 } else
5040 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5041 }
5042 if (topLevel == 0) {
5043 /*
5044 * Attribute "use".
5045 */
5046 attr = xmlSchemaGetPropNode(node, "use");
5047 if (attr != NULL) {
5048 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5049 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5050 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5051 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5052 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5053 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5054 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5055 else
5056 xmlSchemaPSimpleTypeErr(ctxt,
5057 XML_SCHEMAP_INVALID_ATTR_USE,
5058 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005059 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005060 attrValue, NULL, NULL, NULL);
5061 } else
5062 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5063 /*
5064 * 3.2.3 : 2
5065 * If default and use are both present, use must have
5066 * the actual value optional.
5067 */
5068 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5069 (ret->defValue != NULL) &&
5070 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5071 xmlSchemaPSimpleTypeErr(ctxt,
5072 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5073 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005074 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005075 "The value must be 'optional' if the attribute "
5076 "'default' is present as well", NULL, NULL);
5077 }
5078 }
5079 /*
5080 * And now for the children...
5081 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005082 child = node->children;
5083 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5085 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005086 }
5087 if (isRef) {
5088 if (child != NULL) {
5089 if (IS_SCHEMA(child, "simpleType"))
5090 /*
5091 * 3.2.3 : 3.2
5092 * If ref is present, then all of <simpleType>,
5093 * form and type must be absent.
5094 */
5095 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5096 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5097 "(annotation?)");
5098 else
5099 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5100 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5101 "(annotation?)");
5102 }
5103 } else {
5104 if (IS_SCHEMA(child, "simpleType")) {
5105 if (ret->typeName != NULL) {
5106 /*
5107 * 3.2.3 : 4
5108 * type and <simpleType> must not both be present.
5109 */
5110 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5111 &repName, (xmlSchemaTypePtr) ret, node, child,
5112 "The attribute 'type' and the <simpleType> child "
5113 "are mutually exclusive", NULL);
5114 } else
5115 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5116 child = child->next;
5117 }
5118 if (child != NULL)
5119 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5120 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5121 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005122 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005123 /*
5124 * Cleanup.
5125 */
5126 if (repName != NULL)
5127 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005128 return (ret);
5129}
5130
5131/**
5132 * xmlSchemaParseAttributeGroup:
5133 * @ctxt: a schema validation context
5134 * @schema: the schema being built
5135 * @node: a subtree containing XML Schema informations
5136 *
5137 * parse a XML schema Attribute Group declaration
5138 * *WARNING* this interface is highly subject to change
5139 *
5140 * Returns the attribute group or NULL in case of error.
5141 */
5142static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005143xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005144 xmlSchemaPtr schema, xmlNodePtr node,
5145 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005146{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005147 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005148 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005149 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005150 const xmlChar *oldcontainer;
5151 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005152
5153 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5154 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005155
5156 nameAttr = xmlSchemaGetPropNode(node, "name");
5157 attr = xmlSchemaGetPropNode(node, "ref");
5158 if ((topLevel) || (attr == NULL)) {
5159 /*
5160 * Parse as an attribute group definition.
5161 * Note that those are allowed at top level only.
5162 */
5163 if (nameAttr == NULL) {
5164 xmlSchemaPMissingAttrErr(ctxt,
5165 XML_SCHEMAP_S4S_ATTR_MISSING,
5166 NULL, NULL, node, "name", NULL);
5167 return (NULL);
5168 }
5169 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5170 /*
5171 * The name is crucial, exit if invalid.
5172 */
5173 if (xmlSchemaPValAttrNode(ctxt,
5174 NULL, NULL, nameAttr,
5175 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5176 return (NULL);
5177 }
5178 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5179 if (ret == NULL)
5180 return (NULL);
5181 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5182 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5183 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005184 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005185 } else {
5186 char buf[50];
5187 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5188
5189 /*
5190 * Parse as an attribute group definition reference.
5191 */
5192 if (attr == NULL) {
5193 xmlSchemaPMissingAttrErr(ctxt,
5194 XML_SCHEMAP_S4S_ATTR_MISSING,
5195 NULL, NULL, node, "ref", NULL);
5196 }
5197 xmlSchemaPValAttrNodeQName(ctxt, schema,
5198 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5199
5200 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5201 name = (const xmlChar *) buf;
5202 if (name == NULL) {
5203 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5204 "attribute group definition reference", node);
5205 return (NULL);
5206 }
5207 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5208 if (ret == NULL)
5209 return (NULL);
5210 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5211 ret->ref = ref;
5212 ret->refNs = refNs;
5213 /* TODO: Is @refPrefix currently used? */
5214 ret->refPrefix = refPrefix;
5215 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005216 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005217 /*
5218 * Check for illegal attributes.
5219 */
5220 attr = node->properties;
5221 while (attr != NULL) {
5222 if (attr->ns == NULL) {
5223 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5224 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5225 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5226 {
5227 xmlSchemaPIllegalAttrErr(ctxt,
5228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5229 NULL, NULL, attr);
5230 }
5231 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5232 xmlSchemaPIllegalAttrErr(ctxt,
5233 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5234 NULL, NULL, attr);
5235 }
5236 attr = attr->next;
5237 }
5238 /* TODO: Validate "id" ? */
5239 /*
5240 * And now for the children...
5241 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005242 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005243 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005244 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005245 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005246 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5247 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005248 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005249 if (topLevel) {
5250 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5251 if (IS_SCHEMA(child, "anyAttribute")) {
5252 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5253 child = child->next;
5254 }
5255 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005256 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005257 xmlSchemaPContentErr(ctxt,
5258 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5259 NULL, NULL, node, child, NULL,
5260 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005261 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005262 ctxt->container = oldcontainer;
5263 return (ret);
5264}
5265
5266/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005267 * xmlSchemaPValAttrFormDefault:
5268 * @value: the value
5269 * @flags: the flags to be modified
5270 * @flagQualified: the specific flag for "qualified"
5271 *
5272 * Returns 0 if the value is valid, 1 otherwise.
5273 */
5274static int
5275xmlSchemaPValAttrFormDefault(const xmlChar *value,
5276 int *flags,
5277 int flagQualified)
5278{
5279 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5280 if ((*flags & flagQualified) == 0)
5281 *flags |= flagQualified;
5282 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5283 return (1);
5284
5285 return (0);
5286}
5287
5288/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005289 * xmlSchemaPValAttrBlockFinal:
5290 * @value: the value
5291 * @flags: the flags to be modified
5292 * @flagAll: the specific flag for "#all"
5293 * @flagExtension: the specific flag for "extension"
5294 * @flagRestriction: the specific flag for "restriction"
5295 * @flagSubstitution: the specific flag for "substitution"
5296 * @flagList: the specific flag for "list"
5297 * @flagUnion: the specific flag for "union"
5298 *
5299 * Validates the value of the attribute "final" and "block". The value
5300 * is converted into the specified flag values and returned in @flags.
5301 *
5302 * Returns 0 if the value is valid, 1 otherwise.
5303 */
5304
5305static int
5306xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5307 int *flags,
5308 int flagAll,
5309 int flagExtension,
5310 int flagRestriction,
5311 int flagSubstitution,
5312 int flagList,
5313 int flagUnion)
5314{
5315 int ret = 0;
5316
5317 /*
5318 * TODO: This does not check for dublicate entries.
5319 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005320 if (value == NULL)
5321 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005322 if (xmlStrEqual(value, BAD_CAST "#all")) {
5323 if (flagAll != -1)
5324 *flags |= flagAll;
5325 else {
5326 if (flagExtension != -1)
5327 *flags |= flagExtension;
5328 if (flagRestriction != -1)
5329 *flags |= flagRestriction;
5330 if (flagSubstitution != -1)
5331 *flags |= flagSubstitution;
5332 if (flagList != -1)
5333 *flags |= flagList;
5334 if (flagUnion != -1)
5335 *flags |= flagUnion;
5336 }
5337 } else {
5338 const xmlChar *end, *cur = value;
5339 xmlChar *item;
5340
5341 do {
5342 while (IS_BLANK_CH(*cur))
5343 cur++;
5344 end = cur;
5345 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5346 end++;
5347 if (end == cur)
5348 break;
5349 item = xmlStrndup(cur, end - cur);
5350 if (xmlStrEqual(item, BAD_CAST "extension")) {
5351 if (flagExtension != -1) {
5352 if ((*flags & flagExtension) == 0)
5353 *flags |= flagExtension;
5354 } else
5355 ret = 1;
5356 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5357 if (flagRestriction != -1) {
5358 if ((*flags & flagRestriction) == 0)
5359 *flags |= flagRestriction;
5360 } else
5361 ret = 1;
5362 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5363 if (flagSubstitution != -1) {
5364 if ((*flags & flagSubstitution) == 0)
5365 *flags |= flagSubstitution;
5366 } else
5367 ret = 1;
5368 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5369 if (flagList != -1) {
5370 if ((*flags & flagList) == 0)
5371 *flags |= flagList;
5372 } else
5373 ret = 1;
5374 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5375 if (flagUnion != -1) {
5376 if ((*flags & flagUnion) == 0)
5377 *flags |= flagUnion;
5378 } else
5379 ret = 1;
5380 } else
5381 ret = 1;
5382 if (item != NULL)
5383 xmlFree(item);
5384 cur = end;
5385 } while ((ret == 0) && (*cur != 0));
5386 }
5387
5388 return (ret);
5389}
5390
5391/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005392 * xmlSchemaParseElement:
5393 * @ctxt: a schema validation context
5394 * @schema: the schema being built
5395 * @node: a subtree containing XML Schema informations
5396 *
5397 * parse a XML schema Element declaration
5398 * *WARNING* this interface is highly subject to change
5399 *
William M. Bracke7091952004-05-11 15:09:58 +00005400 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005401 */
5402static xmlSchemaElementPtr
5403xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005404 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005405{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005406 const xmlChar *name = NULL;
5407 const xmlChar *attrValue;
5408 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005409 xmlSchemaElementPtr ret;
5410 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005411 const xmlChar *oldcontainer;
5412 xmlAttrPtr attr, nameAttr;
5413 int minOccurs, maxOccurs;
5414 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005415
5416 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5417 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005418
Daniel Veillard4255d502002-04-16 15:50:10 +00005419 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5420 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005421
Daniel Veillardc0826a72004-08-10 14:17:33 +00005422 oldcontainer = ctxt->container;
5423
5424 nameAttr = xmlSchemaGetPropNode(node, "name");
5425 attr = xmlSchemaGetPropNode(node, "ref");
5426 if ((topLevel) || (attr == NULL)) {
5427 if (nameAttr == NULL) {
5428 xmlSchemaPMissingAttrErr(ctxt,
5429 XML_SCHEMAP_S4S_ATTR_MISSING,
5430 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5431 "name", NULL);
5432 return (NULL);
5433 }
5434 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5435 } else {
5436 isRef = 1;
5437
5438 }
5439 /*
5440 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5441 * to no component at all
5442 * TODO: It might be better to validate the element, even if it won't be
5443 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005444 */
5445 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5446 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005447 if ((minOccurs == 0) && (maxOccurs == 0))
5448 return (NULL);
5449 /*
5450 * If we get a "ref" attribute on a local <element> we will assume it's
5451 * a reference - even if there's a "name" attribute; this seems to be more
5452 * robust.
5453 */
5454 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005455 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005456 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5457
5458 /*
5459 * Parse as a particle.
5460 */
5461 xmlSchemaPValAttrNodeQName(ctxt, schema,
5462 (xmlChar **) &xmlSchemaElemDesAttrRef,
5463 NULL, attr, &refNs, &refPrefix, &ref);
5464
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005465 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005466 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005467 if (ret == NULL) {
5468 if (repName != NULL)
5469 xmlFree(repName);
5470 return (NULL);
5471 }
5472 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5473 ret->node = node;
5474 ret->ref = ref;
5475 ret->refNs = refNs;
5476 ret->refPrefix = refPrefix;
5477 ret->flags |= XML_SCHEMAS_ELEM_REF;
5478 /*
5479 * Check for illegal attributes.
5480 */
5481 /*
5482 * 3.3.3 : 2.1
5483 * One of ref or name must be present, but not both
5484 */
5485 if (nameAttr != NULL) {
5486 xmlSchemaPMutualExclAttrErr(ctxt,
5487 XML_SCHEMAP_SRC_ELEMENT_2_1,
5488 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5489 "ref", "name");
5490 }
5491 /* 3.3.3 : 2.2 */
5492 attr = node->properties;
5493 while (attr != NULL) {
5494 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005495 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5496 xmlStrEqual(attr->name, BAD_CAST "name") ||
5497 xmlStrEqual(attr->name, BAD_CAST "id") ||
5498 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5499 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5500 {
5501 attr = attr->next;
5502 continue;
5503 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005504 xmlSchemaPCustomAttrErr(ctxt,
5505 XML_SCHEMAP_SRC_ELEMENT_2_2,
5506 &repName, (xmlSchemaTypePtr) ret, attr,
5507 "Only the attributes 'minOccurs', 'maxOccurs' and "
5508 "'id' are allowed in addition to 'ref'");
5509 break;
5510 }
5511 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5512 xmlSchemaPIllegalAttrErr(ctxt,
5513 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5514 &repName, (xmlSchemaTypePtr) ret, attr);
5515 }
5516 attr = attr->next;
5517 }
5518 } else {
5519 const xmlChar *ns = NULL, *fixed;
5520
5521 /*
5522 * Parse as an element declaration.
5523 */
5524 if (xmlSchemaPValAttrNode(ctxt,
5525 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5526 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5527 return (NULL);
5528 /*
5529 * Evaluate the target namespace.
5530 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005531 if (topLevel) {
5532 ns = schema->targetNamespace;
5533 } else {
5534 attr = xmlSchemaGetPropNode(node, "form");
5535 if (attr != NULL) {
5536 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5537 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005538 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005539 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5540 xmlSchemaPSimpleTypeErr(ctxt,
5541 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5542 &repName, NULL, (xmlNodePtr) attr,
5543 NULL, "(qualified | unqualified)",
5544 attrValue, NULL, NULL, NULL);
5545 }
5546 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5547 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005548 }
5549 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005550 if (ret == NULL) {
5551 if (repName != NULL)
5552 xmlFree(repName);
5553 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005554 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005555 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005556 ret->node = node;
5557 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005558 /*
5559 * Check for illegal attributes.
5560 */
William M. Bracke7091952004-05-11 15:09:58 +00005561 attr = node->properties;
5562 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005563 if (attr->ns == NULL) {
5564 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5565 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5566 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5567 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5568 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5569 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005570 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5571 {
5572 if (topLevel == 0) {
5573 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005574 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005575 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5576 {
5577 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5578 /*
5579 * 3.3.6 : 3 If there is a non-·absent· {substitution
5580 * group affiliation}, then {scope} must be global.
5581 * TODO: This one is redundant, since the S4S does
5582 * prohibit this attribute on local declarations already;
5583 * so why an explicit error code? Weird spec.
5584 * TODO: Move this to the proper constraint layer.
5585 * TODO: Or better wait for spec 1.1 to come.
5586 */
5587 xmlSchemaPIllegalAttrErr(ctxt,
5588 XML_SCHEMAP_E_PROPS_CORRECT_3,
5589 &repName, (xmlSchemaTypePtr) ret, attr);
5590 } else {
5591 xmlSchemaPIllegalAttrErr(ctxt,
5592 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5593 &repName, (xmlSchemaTypePtr) ret, attr);
5594 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005595 }
5596 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5597 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5598 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5599
5600 xmlSchemaPIllegalAttrErr(ctxt,
5601 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5602 &repName, (xmlSchemaTypePtr) ret, attr);
5603 }
5604 }
5605 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5606
5607 xmlSchemaPIllegalAttrErr(ctxt,
5608 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5609 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005610 }
5611 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005612 }
William M. Bracke7091952004-05-11 15:09:58 +00005613 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 * Extract/validate attributes.
5615 */
5616 if (topLevel) {
5617 /*
5618 * Process top attributes of global element declarations here.
5619 */
5620 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5621 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5622 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5623 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5624 &(ret->substGroupNs), NULL, &(ret->substGroup));
5625 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5626 node, "abstract", 0))
5627 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5628 /*
5629 * Attribute "final".
5630 */
5631 attr = xmlSchemaGetPropNode(node, "final");
5632 if (attr == NULL) {
5633 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5634 } else {
5635 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5636 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5637 -1,
5638 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5639 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5640 xmlSchemaPSimpleTypeErr(ctxt,
5641 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5642 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005643 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005644 attrValue, NULL, NULL, NULL);
5645 }
5646 }
5647 }
5648 /*
5649 * Attribute "block".
5650 */
5651 attr = xmlSchemaGetPropNode(node, "block");
5652 if (attr == NULL) {
5653 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5654 } else {
5655 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5656 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5657 -1,
5658 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5659 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5660 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5661 xmlSchemaPSimpleTypeErr(ctxt,
5662 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5663 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005664 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005665 "restriction | substitution))", attrValue,
5666 NULL, NULL, NULL);
5667 }
5668 }
5669 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5670 node, "nillable", 0))
5671 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005672
Daniel Veillardc0826a72004-08-10 14:17:33 +00005673 xmlSchemaPValAttrQName(ctxt, schema,
5674 &repName, (xmlSchemaTypePtr) ret, node,
5675 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005676
Daniel Veillardc0826a72004-08-10 14:17:33 +00005677 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5678 attr = xmlSchemaGetPropNode(node, "fixed");
5679 if (attr != NULL) {
5680 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5681 if (ret->value != NULL) {
5682 /*
5683 * 3.3.3 : 1
5684 * default and fixed must not both be present.
5685 */
5686 xmlSchemaPMutualExclAttrErr(ctxt,
5687 XML_SCHEMAP_SRC_ELEMENT_1,
5688 &repName, (xmlSchemaTypePtr) ret, attr,
5689 "default", "fixed");
5690 } else {
5691 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5692 ret->value = fixed;
5693 }
5694 }
5695 }
5696 /*
5697 * Extract/validate common attributes.
5698 */
5699 /* TODO: Check ID: */
5700 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5701 ret->minOccurs = minOccurs;
5702 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005703 if (topLevel != 1)
5704 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5705 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005706 /*
5707 * And now for the children...
5708 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005709 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005710 child = node->children;
5711 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005712 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5713 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005714 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005715 if (isRef) {
5716 if (child != NULL) {
5717 xmlSchemaPContentErr(ctxt,
5718 XML_SCHEMAP_SRC_ELEMENT_2_2,
5719 &repName, (xmlSchemaTypePtr) ret, node, child,
5720 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005721 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005722 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005723 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 /*
5725 * 3.3.3 : 3
5726 * "type" and either <simpleType> or <complexType> are mutually
5727 * exclusive
5728 */
William M. Bracke7091952004-05-11 15:09:58 +00005729 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005730 xmlSchemaPContentErr(ctxt,
5731 XML_SCHEMAP_SRC_ELEMENT_3,
5732 &repName, (xmlSchemaTypePtr) ret, node, child,
5733 "The attribute 'type' and the <complexType> child are "
5734 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005735 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005736 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005737 child = child->next;
5738 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005739 /*
5740 * 3.3.3 : 3
5741 * "type" and either <simpleType> or <complexType> are
5742 * mutually exclusive
5743 */
William M. Bracke7091952004-05-11 15:09:58 +00005744 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005745 xmlSchemaPContentErr(ctxt,
5746 XML_SCHEMAP_SRC_ELEMENT_3,
5747 &repName, (xmlSchemaTypePtr) ret, node, child,
5748 "The attribute 'type' and the <simpleType> child are "
5749 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005750 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005751 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005752 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005753 }
William M. Bracke7091952004-05-11 15:09:58 +00005754 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005755 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcik48307f42004-11-12 15:16:25 +00005756 TODO child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00005757 }
5758 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 xmlSchemaPContentErr(ctxt,
5760 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5761 &repName, (xmlSchemaTypePtr) ret, node, child,
5762 NULL, "(annotation?, ((simpleType | complexType)?, "
5763 "(unique | key | keyref)*))");
5764 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005765
Daniel Veillardc0826a72004-08-10 14:17:33 +00005766 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005767 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005768 /*
5769 * Cleanup.
5770 */
5771 if (repName != NULL)
5772 xmlFree(repName);
5773 /*
5774 * NOTE: Element Declaration Representation OK 4. will be checked at a
5775 * different layer.
5776 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005777 return (ret);
5778}
5779
5780/**
5781 * xmlSchemaParseUnion:
5782 * @ctxt: a schema validation context
5783 * @schema: the schema being built
5784 * @node: a subtree containing XML Schema informations
5785 *
5786 * parse a XML schema Union definition
5787 * *WARNING* this interface is highly subject to change
5788 *
William M. Bracke7091952004-05-11 15:09:58 +00005789 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005790 * 1 in case of success.
5791 */
5792static xmlSchemaTypePtr
5793xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005794 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005795{
5796 xmlSchemaTypePtr type, subtype, last = NULL;
5797 xmlNodePtr child = NULL;
5798 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005799 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005800
5801 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5802 return (NULL);
5803
William M. Brack2f2a6632004-08-20 23:09:47 +00005804 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5805 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 if (type == NULL)
5807 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005808 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005810 /*
5811 * Check for illegal attributes.
5812 */
5813 attr = node->properties;
5814 while (attr != NULL) {
5815 if (attr->ns == NULL) {
5816 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5817 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5818 xmlSchemaPIllegalAttrErr(ctxt,
5819 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5820 NULL, type, attr);
5821 }
5822 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5823 xmlSchemaPIllegalAttrErr(ctxt,
5824 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5825 NULL, type, attr);
5826 }
5827 attr = attr->next;
5828 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005829 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005830 /*
5831 * Attribute "memberTypes". This is a list of QNames.
5832 * TODO: Validate the QNames.
5833 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005834 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005835 /*
5836 * And now for the children...
5837 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005838 child = node->children;
5839 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005840 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5841 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005842 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005843 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005844 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005845 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005846 if (subtype != NULL) {
5847 if (last == NULL) {
5848 type->subtypes = subtype;
5849 last = subtype;
5850 } else {
5851 last->next = subtype;
5852 last = subtype;
5853 }
5854 last->next = NULL;
5855 }
5856 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005857 }
5858 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005859 /* TODO: Think about the error code. */
5860 xmlSchemaPContentErr(ctxt,
5861 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5862 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005863 }
5864 return (type);
5865}
5866
5867/**
5868 * xmlSchemaParseList:
5869 * @ctxt: a schema validation context
5870 * @schema: the schema being built
5871 * @node: a subtree containing XML Schema informations
5872 *
5873 * parse a XML schema List definition
5874 * *WARNING* this interface is highly subject to change
5875 *
William M. Bracke7091952004-05-11 15:09:58 +00005876 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005877 * 1 in case of success.
5878 */
5879static xmlSchemaTypePtr
5880xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005881 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005882{
5883 xmlSchemaTypePtr type, subtype;
5884 xmlNodePtr child = NULL;
5885 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005886 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005887
5888 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5889 return (NULL);
5890
William M. Brack2f2a6632004-08-20 23:09:47 +00005891 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5892 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005893 if (type == NULL)
5894 return (NULL);
5895 type->node = node;
5896 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005897 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005898 /*
5899 * Check for illegal attributes.
5900 */
5901 attr = node->properties;
5902 while (attr != NULL) {
5903 if (attr->ns == NULL) {
5904 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5905 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5906 xmlSchemaPIllegalAttrErr(ctxt,
5907 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5908 NULL, type, attr);
5909 }
5910 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5911 xmlSchemaPIllegalAttrErr(ctxt,
5912 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5913 NULL, type, attr);
5914 }
5915 attr = attr->next;
5916 }
5917 /*
5918 * Attribute "itemType".
5919 */
5920 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5921 node, "itemType", &(type->baseNs), NULL, &(type->base));
5922 /*
5923 * And now for the children...
5924 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005925 child = node->children;
5926 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005927 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5928 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005929 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005930 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005931 if (IS_SCHEMA(child, "simpleType")) {
5932 if (type->base != NULL) {
5933 xmlSchemaPCustomErr(ctxt,
5934 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5935 NULL, type, node,
5936 "The attribute 'itemType' and the <simpleType> child "
5937 "are mutually exclusive", NULL);
5938 } else {
5939 subtype = (xmlSchemaTypePtr)
5940 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5941 type->subtypes = subtype;
5942 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005943 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005944 }
5945 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005946 /* TODO: Think about the error code. */
5947 xmlSchemaPContentErr(ctxt,
5948 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5949 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005950 }
5951 return (type);
5952}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005953
Daniel Veillard4255d502002-04-16 15:50:10 +00005954/**
5955 * xmlSchemaParseSimpleType:
5956 * @ctxt: a schema validation context
5957 * @schema: the schema being built
5958 * @node: a subtree containing XML Schema informations
5959 *
5960 * parse a XML schema Simple Type definition
5961 * *WARNING* this interface is highly subject to change
5962 *
William M. Bracke7091952004-05-11 15:09:58 +00005963 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005964 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005965 */
5966static xmlSchemaTypePtr
5967xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005968 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005969{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005970 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005971 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005972 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005973 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005975
5976 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5977 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005978
Daniel Veillardc0826a72004-08-10 14:17:33 +00005979 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005980 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005981 if (attr == NULL) {
5982 xmlSchemaPMissingAttrErr(ctxt,
5983 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005984 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005985 "name", NULL);
5986 return (NULL);
5987 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005988 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005989 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005990 return (NULL);
5991 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005992 }
5993
5994 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005995 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005996
Daniel Veillard01fa6152004-06-29 17:04:39 +00005997 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005998 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005999 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006000 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006001 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006002 if (type == NULL)
6003 return (NULL);
6004 type->node = node;
6005 type->type = XML_SCHEMA_TYPE_SIMPLE;
6006 /*
6007 * Check for illegal attributes.
6008 */
6009 attr = node->properties;
6010 while (attr != NULL) {
6011 if (attr->ns == NULL) {
6012 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6013 xmlSchemaPIllegalAttrErr(ctxt,
6014 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006015 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006016 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006017 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6018 xmlSchemaPIllegalAttrErr(ctxt,
6019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006020 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006021 }
6022 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006023 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006024 } else {
6025 /*
6026 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006027 *
6028 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006029 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006030 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006031 if (type == NULL)
6032 return (NULL);
6033 type->node = node;
6034 type->type = XML_SCHEMA_TYPE_SIMPLE;
6035 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6036 /*
6037 * Check for illegal attributes.
6038 */
6039 attr = node->properties;
6040 while (attr != NULL) {
6041 if (attr->ns == NULL) {
6042 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6043 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006044 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006045 xmlSchemaPIllegalAttrErr(ctxt,
6046 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006047 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006048 }
6049 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6050 xmlSchemaPIllegalAttrErr(ctxt,
6051 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006052 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006053 }
6054 attr = attr->next;
6055 }
6056 /*
6057 * Attribute "final".
6058 */
6059 attr = xmlSchemaGetPropNode(node, "final");
6060 if (attr == NULL) {
6061 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6062 } else {
6063 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6064 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6065 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6066 XML_SCHEMAS_TYPE_FINAL_LIST,
6067 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6068
6069 xmlSchemaPSimpleTypeErr(ctxt,
6070 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006071 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006072 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006073 attrValue, NULL, NULL, NULL);
6074 }
6075 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006076 }
6077 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006078 /* TODO: Check id. */
6079 type->id = xmlSchemaGetProp(ctxt, node, "id");
6080 /*
6081 * And now for the children...
6082 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006083 oldCtxtType = ctxt->ctxtType;
6084 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006085 ctxt->ctxtType = type;
6086 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 child = node->children;
6088 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006089 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6090 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006092 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006093 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006094 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006095 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006096 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006097 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006098 subtype = (xmlSchemaTypePtr)
6099 xmlSchemaParseList(ctxt, schema, child);
6100 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006101 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006102 subtype = (xmlSchemaTypePtr)
6103 xmlSchemaParseUnion(ctxt, schema, child);
6104 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006105 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006106 type->subtypes = subtype;
6107 if ((child != NULL) || (subtype == NULL)) {
6108 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006109 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006110 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006111 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006112 ctxt->parentItem = oldParentItem;
6113 ctxt->ctxtType = oldCtxtType;
6114 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006115
Daniel Veillard4255d502002-04-16 15:50:10 +00006116 return (type);
6117}
6118
6119
6120/**
6121 * xmlSchemaParseGroup:
6122 * @ctxt: a schema validation context
6123 * @schema: the schema being built
6124 * @node: a subtree containing XML Schema informations
6125 *
6126 * parse a XML schema Group definition
6127 * *WARNING* this interface is highly subject to change
6128 *
William M. Bracke7091952004-05-11 15:09:58 +00006129 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006130 * 1 in case of success.
6131 */
6132static xmlSchemaTypePtr
6133xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006134 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006135{
6136 xmlSchemaTypePtr type, subtype;
6137 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006138 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006139 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006140 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006141 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006142
6143 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6144 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006145 /*
6146 * TODO: Validate the element even if no item is created
6147 * (i.e. min/maxOccurs == 0).
6148 */
6149 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6150 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6151 if ((minOccurs == 0) && (maxOccurs == 0)) {
6152 return (NULL);
6153 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006154 if (topLevel)
6155 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006156 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006157 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006158 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6159 if (ref == NULL) {
6160 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006161 XML_SCHEMAP_GROUP_NONAME_NOREF,
6162 "Group definition or particle: One of the attributes \"name\" "
6163 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006164 return (NULL);
6165 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006166 if (refNs == NULL)
6167 refNs = schema->targetNamespace;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006168 snprintf(buf, 49, "#GrRef %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006169 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006170 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006171 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006172 if (type == NULL)
6173 return (NULL);
6174 type->node = node;
6175 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006176 if (topLevel)
6177 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006178 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006179 type->ref = ref;
6180 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006181 type->minOccurs = minOccurs;
6182 type->maxOccurs = maxOccurs;
6183 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006184 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006185
6186 child = node->children;
6187 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006188 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6189 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006190 }
6191 subtype = NULL;
6192 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006193 subtype = (xmlSchemaTypePtr)
6194 xmlSchemaParseAll(ctxt, schema, child);
6195 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006196 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006197 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006199 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006200 subtype = (xmlSchemaTypePtr)
6201 xmlSchemaParseSequence(ctxt, schema, child);
6202 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006203 }
6204 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006205 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006206 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006207 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006208 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006209 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006210 }
6211
6212 return (type);
6213}
6214
6215/**
6216 * xmlSchemaParseAll:
6217 * @ctxt: a schema validation context
6218 * @schema: the schema being built
6219 * @node: a subtree containing XML Schema informations
6220 *
6221 * parse a XML schema All definition
6222 * *WARNING* this interface is highly subject to change
6223 *
William M. Bracke7091952004-05-11 15:09:58 +00006224 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006225 * 1 in case of success.
6226 */
6227static xmlSchemaTypePtr
6228xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006229 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006230{
6231 xmlSchemaTypePtr type, subtype, last = NULL;
6232 xmlNodePtr child = NULL;
6233 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006234 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006235
6236 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6237 return (NULL);
6238
6239
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006240 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006241 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006242 if (type == NULL)
6243 return (NULL);
6244 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006245 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006246 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006247
6248 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6249 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006250
6251 oldcontainer = ctxt->container;
6252 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006253 child = node->children;
6254 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006255 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6256 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006257 }
6258 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006259 subtype = (xmlSchemaTypePtr)
6260 xmlSchemaParseElement(ctxt, schema, child, 0);
6261 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006262 if (subtype->minOccurs > 1)
6263 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006264 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006265 NULL, NULL);
6266 if (subtype->maxOccurs > 1)
6267 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006268 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006269 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006270 if (last == NULL) {
6271 type->subtypes = subtype;
6272 last = subtype;
6273 } else {
6274 last->next = subtype;
6275 last = subtype;
6276 }
6277 last->next = NULL;
6278 }
6279 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006280 }
6281 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006282 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006283 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006284 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006285 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006286 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006287 return (type);
6288}
6289
6290/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006291 * xmlSchemaCleanupDoc:
6292 * @ctxt: a schema validation context
6293 * @node: the root of the document.
6294 *
6295 * removes unwanted nodes in a schemas document tree
6296 */
6297static void
6298xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6299{
6300 xmlNodePtr delete, cur;
6301
6302 if ((ctxt == NULL) || (root == NULL)) return;
6303
6304 /*
6305 * Remove all the blank text nodes
6306 */
6307 delete = NULL;
6308 cur = root;
6309 while (cur != NULL) {
6310 if (delete != NULL) {
6311 xmlUnlinkNode(delete);
6312 xmlFreeNode(delete);
6313 delete = NULL;
6314 }
6315 if (cur->type == XML_TEXT_NODE) {
6316 if (IS_BLANK_NODE(cur)) {
6317 if (xmlNodeGetSpacePreserve(cur) != 1) {
6318 delete = cur;
6319 }
6320 }
6321 } else if ((cur->type != XML_ELEMENT_NODE) &&
6322 (cur->type != XML_CDATA_SECTION_NODE)) {
6323 delete = cur;
6324 goto skip_children;
6325 }
6326
6327 /*
6328 * Skip to next node
6329 */
6330 if (cur->children != NULL) {
6331 if ((cur->children->type != XML_ENTITY_DECL) &&
6332 (cur->children->type != XML_ENTITY_REF_NODE) &&
6333 (cur->children->type != XML_ENTITY_NODE)) {
6334 cur = cur->children;
6335 continue;
6336 }
6337 }
6338 skip_children:
6339 if (cur->next != NULL) {
6340 cur = cur->next;
6341 continue;
6342 }
6343
6344 do {
6345 cur = cur->parent;
6346 if (cur == NULL)
6347 break;
6348 if (cur == root) {
6349 cur = NULL;
6350 break;
6351 }
6352 if (cur->next != NULL) {
6353 cur = cur->next;
6354 break;
6355 }
6356 } while (cur != NULL);
6357 }
6358 if (delete != NULL) {
6359 xmlUnlinkNode(delete);
6360 xmlFreeNode(delete);
6361 delete = NULL;
6362 }
6363}
6364
William M. Brack2f2a6632004-08-20 23:09:47 +00006365
6366/**
6367 * xmlSchemaImportSchema
6368 *
6369 * @ctxt: a schema validation context
6370 * @schemaLocation: an URI defining where to find the imported schema
6371 *
6372 * import a XML schema
6373 * *WARNING* this interface is highly subject to change
6374 *
6375 * Returns -1 in case of error and 1 in case of success.
6376 */
6377#if 0
6378static xmlSchemaImportPtr
6379xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6380 const xmlChar *schemaLocation)
6381{
6382 xmlSchemaImportPtr import;
6383 xmlSchemaParserCtxtPtr newctxt;
6384
6385 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6386 if (newctxt == NULL) {
6387 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6388 NULL);
6389 return (NULL);
6390 }
6391 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6392 /* Keep the same dictionnary for parsing, really */
6393 xmlDictReference(ctxt->dict);
6394 newctxt->dict = ctxt->dict;
6395 newctxt->includes = 0;
6396 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6397
6398 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6399 ctxt->userData);
6400
6401 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6402 if (import == NULL) {
6403 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6404 NULL);
6405 xmlSchemaFreeParserCtxt(newctxt);
6406 return (NULL);
6407 }
6408
6409 memset(import, 0, sizeof(xmlSchemaImport));
6410 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6411 import->schema = xmlSchemaParse(newctxt);
6412
6413 if (import->schema == NULL) {
6414 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006415 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006416 "Failed to import schema from location \"%s\".\n",
6417 schemaLocation, NULL);
6418
6419 xmlSchemaFreeParserCtxt(newctxt);
6420 /* The schemaLocation is held by the dictionary.
6421 if (import->schemaLocation != NULL)
6422 xmlFree((xmlChar *)import->schemaLocation);
6423 */
6424 xmlFree(import);
6425 return NULL;
6426 }
6427
6428 xmlSchemaFreeParserCtxt(newctxt);
6429 return import;
6430}
6431#endif
6432
6433static void
6434xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6435{
6436 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6437 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6438
6439 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6440 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6441
6442 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6443 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6444 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6445 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6446 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6447 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6448 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6449 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6450
6451 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6452 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6453 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6454 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6455 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6456 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6457}
6458
6459static void
6460xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6461 xmlSchemaPtr schema,
6462 xmlNodePtr node)
6463{
6464 xmlAttrPtr attr;
6465 const xmlChar *val;
6466
6467 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6468 if (attr != NULL) {
6469 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6470 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6471 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6472 xmlSchemaPSimpleTypeErr(ctxt,
6473 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6474 NULL, NULL, (xmlNodePtr) attr, NULL,
6475 "(qualified | unqualified)", val, NULL, NULL, NULL);
6476 }
6477 }
6478
6479 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6480 if (attr != NULL) {
6481 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6482 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6483 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6484 xmlSchemaPSimpleTypeErr(ctxt,
6485 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6486 NULL, NULL, (xmlNodePtr) attr, NULL,
6487 "(qualified | unqualified)", val, NULL, NULL, NULL);
6488 }
6489 }
6490
6491 attr = xmlSchemaGetPropNode(node, "finalDefault");
6492 if (attr != NULL) {
6493 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6494 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6495 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6496 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6497 -1,
6498 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6499 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6500 xmlSchemaPSimpleTypeErr(ctxt,
6501 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6502 NULL, NULL, (xmlNodePtr) attr, NULL,
6503 "(#all | List of (extension | restriction | list | union))",
6504 val, NULL, NULL, NULL);
6505 }
6506 }
6507
6508 attr = xmlSchemaGetPropNode(node, "blockDefault");
6509 if (attr != NULL) {
6510 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6511 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6512 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6513 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6514 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6515 xmlSchemaPSimpleTypeErr(ctxt,
6516 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6517 NULL, NULL, (xmlNodePtr) attr, NULL,
6518 "(#all | List of (extension | restriction | substitution))",
6519 val, NULL, NULL, NULL);
6520 }
6521 }
6522}
6523
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006524/**
6525 * xmlSchemaParseSchemaTopLevel:
6526 * @ctxt: a schema validation context
6527 * @schema: the schemas
6528 * @nodes: the list of top level nodes
6529 *
6530 * Returns the internal XML Schema structure built from the resource or
6531 * NULL in case of error
6532 */
6533static void
6534xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6535 xmlSchemaPtr schema, xmlNodePtr nodes)
6536{
6537 xmlNodePtr child;
6538 xmlSchemaAnnotPtr annot;
6539
6540 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6541 return;
6542
6543 child = nodes;
6544 while ((IS_SCHEMA(child, "include")) ||
6545 (IS_SCHEMA(child, "import")) ||
6546 (IS_SCHEMA(child, "redefine")) ||
6547 (IS_SCHEMA(child, "annotation"))) {
6548 if (IS_SCHEMA(child, "annotation")) {
6549 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6550 if (schema->annot == NULL)
6551 schema->annot = annot;
6552 else
6553 xmlSchemaFreeAnnot(annot);
6554 } else if (IS_SCHEMA(child, "import")) {
6555 xmlSchemaParseImport(ctxt, schema, child);
6556 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006557 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006558 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006559 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006560 } else if (IS_SCHEMA(child, "redefine")) {
6561 TODO
6562 }
6563 child = child->next;
6564 }
6565 while (child != NULL) {
6566 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006567 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006568 child = child->next;
6569 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006570 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006571 child = child->next;
6572 } else if (IS_SCHEMA(child, "element")) {
6573 xmlSchemaParseElement(ctxt, schema, child, 1);
6574 child = child->next;
6575 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006576 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006577 child = child->next;
6578 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006579 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006580 child = child->next;
6581 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006582 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006583 child = child->next;
6584 } else if (IS_SCHEMA(child, "notation")) {
6585 xmlSchemaParseNotation(ctxt, schema, child);
6586 child = child->next;
6587 } else {
6588 xmlSchemaPErr2(ctxt, NULL, child,
6589 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006590 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006591 child->name, NULL);
6592 child = child->next;
6593 }
6594 while (IS_SCHEMA(child, "annotation")) {
6595 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6596 if (schema->annot == NULL)
6597 schema->annot = annot;
6598 else
6599 xmlSchemaFreeAnnot(annot);
6600 child = child->next;
6601 }
6602 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006603 ctxt->parentItem = NULL;
6604 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006605}
6606
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006607static xmlSchemaImportPtr
6608xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6609 xmlHashTablePtr *imports,
6610 const xmlChar *nsName)
6611{
6612 xmlSchemaImportPtr ret;
6613
6614 if (*imports == NULL) {
6615 *imports = xmlHashCreate(10);
6616 if (*imports == NULL) {
6617 xmlSchemaPCustomErr(ctxt,
6618 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6619 NULL, NULL, (xmlNodePtr) ctxt->doc,
6620 "Internal error: failed to build the import table",
6621 NULL);
6622 return (NULL);
6623 }
6624 }
6625 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6626 if (ret == NULL) {
6627 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6628 return (NULL);
6629 }
6630 memset(ret, 0, sizeof(xmlSchemaImport));
6631 if (nsName == NULL)
6632 nsName = XML_SCHEMAS_NO_NAMESPACE;
6633 xmlHashAddEntry(*imports, nsName, ret);
6634
6635 return (ret);
6636}
6637
6638static int
6639xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006640 xmlSchemaPtr schema,
6641 xmlNodePtr node,
6642 const xmlChar *nsName,
6643 const xmlChar *location,
6644 xmlDocPtr *doc,
6645 const xmlChar **targetNamespace,
6646 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006647{
6648 xmlParserCtxtPtr parserCtxt;
6649 xmlSchemaImportPtr import;
6650 const xmlChar *ns;
6651 xmlNodePtr root;
6652
6653 /*
6654 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6655 * <xsi:noNamespaceSchemaLocation>.
6656 */
6657 *doc = NULL;
6658 /*
6659 * Given that the schemaLocation [attribute] is only a hint, it is open
6660 * to applications to ignore all but the first <import> for a given
6661 * namespace, regardless of the ·actual value· of schemaLocation, but
6662 * such a strategy risks missing useful information when new
6663 * schemaLocations are offered.
6664 *
6665 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6666 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6667 * valid or not.
6668 * We will follow XSV here.
6669 */
6670 if (location == NULL) {
6671 /*
6672 * Schema Document Location Strategy:
6673 *
6674 * 3 Based on the namespace name, identify an existing schema document,
6675 * either as a resource which is an XML document or a <schema> element
6676 * information item, in some local schema repository;
6677 *
6678 * 5 Attempt to resolve the namespace name to locate such a resource.
6679 *
6680 * NOTE: Those stategies are not supported, so we will skip.
6681 */
6682 return (0);
6683 }
6684 if (nsName == NULL)
6685 ns = XML_SCHEMAS_NO_NAMESPACE;
6686 else
6687 ns = nsName;
6688
6689 import = xmlHashLookup(schema->schemasImports, ns);
6690 if (import != NULL) {
6691 /*
6692 * There was a valid resource for the specified namespace already
6693 * defined, so skip.
6694 * TODO: This might be changed someday to allow import of
6695 * components from multiple documents for a single target namespace.
6696 */
6697 return (0);
6698 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006699
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006700 /*
6701 * Schema Document Location Strategy:
6702 *
6703 * 2 Based on the location URI, identify an existing schema document,
6704 * either as a resource which is an XML document or a <schema> element
6705 * information item, in some local schema repository;
6706 *
6707 * 4 Attempt to resolve the location URI, to locate a resource on the
6708 * web which is or contains or references a <schema> element;
6709 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6710 *
6711 */
6712 if ((absolute == 0) && (node != NULL)) {
6713 xmlChar *base, *URI;
6714
6715 base = xmlNodeGetBase(node->doc, node);
6716 if (base == NULL) {
6717 URI = xmlBuildURI(location, node->doc->URL);
6718 } else {
6719 URI = xmlBuildURI(location, base);
6720 xmlFree(base);
6721 }
6722 if (URI != NULL) {
6723 location = xmlDictLookup(ctxt->dict, URI, -1);
6724 xmlFree(URI);
6725 }
6726 }
6727 parserCtxt = xmlNewParserCtxt();
6728 if (parserCtxt == NULL) {
6729 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6730 "allocating a parser context", NULL);
6731 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00006732 }
6733
6734 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
6735 xmlDictFree(parserCtxt->dict);
6736 parserCtxt->dict = ctxt->dict;
6737 xmlDictReference(parserCtxt->dict);
6738 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006739
6740 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6741 NULL, SCHEMAS_PARSE_OPTIONS);
6742
6743 /*
6744 * 2.1 The referent is (a fragment of) a resource which is an
6745 * XML document (see clause 1.1), which in turn corresponds to
6746 * a <schema> element information item in a well-formed information
6747 * set, which in turn corresponds to a valid schema.
6748 * TODO: What to do with the "fragment" stuff?
6749 *
6750 * 2.2 The referent is a <schema> element information item in
6751 * a well-formed information set, which in turn corresponds
6752 * to a valid schema.
6753 * NOTE: 2.2 won't apply, since only XML documents will be processed
6754 * here.
6755 */
6756 if (*doc == NULL) {
6757 xmlErrorPtr lerr;
6758 /*
6759 * It is *not* an error for the application schema reference
6760 * strategy to fail.
6761 *
6762 * If the doc is NULL and the parser error is an IO error we
6763 * will assume that the resource could not be located or accessed.
6764 *
6765 * TODO: Try to find specific error codes to react only on
6766 * localisation failures.
6767 *
6768 * TODO, FIXME: Check the spec: is a namespace added to the imported
6769 * namespaces, even if the schemaLocation did not provide
6770 * a resource? I guess so, since omitting the "schemaLocation"
6771 * attribute, imports a namespace as well.
6772 */
6773 lerr = xmlGetLastError();
6774 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6775 xmlFreeParserCtxt(parserCtxt);
6776 return(0);
6777 }
6778
6779 xmlSchemaPCustomErr(ctxt,
6780 XML_SCHEMAP_SRC_IMPORT_2_1,
6781 NULL, NULL, node,
6782 "Failed to parse the resource '%s' for import",
6783 location);
6784 xmlFreeParserCtxt(parserCtxt);
6785 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6786 }
6787 xmlFreeParserCtxt(parserCtxt);
6788
6789 root = xmlDocGetRootElement(*doc);
6790 if (root == NULL) {
6791 xmlSchemaPCustomErr(ctxt,
6792 XML_SCHEMAP_SRC_IMPORT_2_1,
6793 NULL, NULL, node,
6794 "The XML document '%s' to be imported has no document "
6795 "element", location);
6796 xmlFreeDoc(*doc);
6797 *doc = NULL;
6798 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6799 }
6800
6801 xmlSchemaCleanupDoc(ctxt, root);
6802
6803 if (!IS_SCHEMA(root, "schema")) {
6804 xmlSchemaPCustomErr(ctxt,
6805 XML_SCHEMAP_SRC_IMPORT_2_1,
6806 NULL, NULL, node,
6807 "The XML document '%s' to be imported is not a XML schema document",
6808 location);
6809 xmlFreeDoc(*doc);
6810 *doc = NULL;
6811 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6812 }
6813 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6814 /*
6815 * Schema Representation Constraint: Import Constraints and Semantics
6816 */
6817 if (nsName == NULL) {
6818 if (*targetNamespace != NULL) {
6819 xmlSchemaPCustomErr(ctxt,
6820 XML_SCHEMAP_SRC_IMPORT_3_2,
6821 NULL, NULL, node,
6822 "The XML schema to be imported is not expected "
6823 "to have a target namespace; this differs from "
6824 "its target namespace of '%s'", *targetNamespace);
6825 xmlFreeDoc(*doc);
6826 *doc = NULL;
6827 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6828 }
6829 } else {
6830 if (*targetNamespace == NULL) {
6831 xmlSchemaPCustomErr(ctxt,
6832 XML_SCHEMAP_SRC_IMPORT_3_1,
6833 NULL, NULL, node,
6834 "The XML schema to be imported is expected to have a target "
6835 "namespace of '%s'", nsName);
6836 xmlFreeDoc(*doc);
6837 *doc = NULL;
6838 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6839 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6840 xmlSchemaPCustomErrExt(ctxt,
6841 XML_SCHEMAP_SRC_IMPORT_3_1,
6842 NULL, NULL, node,
6843 "The XML schema to be imported is expected to have a "
6844 "target namespace of '%s'; this differs from "
6845 "its target namespace of '%s'",
6846 nsName, *targetNamespace, NULL);
6847 xmlFreeDoc(*doc);
6848 *doc = NULL;
6849 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6850 }
6851 }
6852
6853 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6854 if (import == NULL) {
6855 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6856 NULL, NULL, NULL,
6857 "Internal error: xmlSchemaAcquireSchemaDoc, "
6858 "failed to build import table", NULL);
6859 xmlFreeDoc(*doc);
6860 *doc = NULL;
6861 return (-1);
6862 }
6863 import->schemaLocation = location;
6864 import->doc = *doc;
6865 return (0);
6866}
William M. Brack2f2a6632004-08-20 23:09:47 +00006867
6868/**
6869 * xmlSchemaParseImport:
6870 * @ctxt: a schema validation context
6871 * @schema: the schema being built
6872 * @node: a subtree containing XML Schema informations
6873 *
6874 * parse a XML schema Import definition
6875 * *WARNING* this interface is highly subject to change
6876 *
6877 * Returns 0 in case of success, a positive error code if
6878 * not valid and -1 in case of an internal error.
6879 */
6880static int
6881xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6882 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006883{
6884 xmlNodePtr child;
6885 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006886 const xmlChar *schemaLocation = NULL;
6887 const xmlChar *targetNamespace, *oldTNS, *url;
6888 xmlAttrPtr attr;
6889 xmlDocPtr doc;
6890 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006891 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006892
6893
6894 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6895 return (-1);
6896
6897 /*
6898 * Check for illegal attributes.
6899 */
6900 attr = node->properties;
6901 while (attr != NULL) {
6902 if (attr->ns == NULL) {
6903 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6904 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6905 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6906 xmlSchemaPIllegalAttrErr(ctxt,
6907 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6908 NULL, NULL, attr);
6909 }
6910 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6911 xmlSchemaPIllegalAttrErr(ctxt,
6912 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6913 NULL, NULL, attr);
6914 }
6915 attr = attr->next;
6916 }
6917 /*
6918 * Extract and validate attributes.
6919 */
6920 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6921 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6922 &namespace) != 0) {
6923 xmlSchemaPSimpleTypeErr(ctxt,
6924 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6925 NULL, NULL, node,
6926 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6927 NULL, namespace, NULL, NULL, NULL);
6928 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6929 }
6930
6931 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6932 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6933 &schemaLocation) != 0) {
6934 xmlSchemaPSimpleTypeErr(ctxt,
6935 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6936 NULL, NULL, node,
6937 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6938 NULL, namespace, NULL, NULL, NULL);
6939 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6940 }
6941 /*
6942 * And now for the children...
6943 */
6944 child = node->children;
6945 if (IS_SCHEMA(child, "annotation")) {
6946 /*
6947 * the annotation here is simply discarded ...
6948 */
6949 child = child->next;
6950 }
6951 if (child != NULL) {
6952 xmlSchemaPContentErr(ctxt,
6953 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6954 NULL, NULL, node, child, NULL,
6955 "(annotation?)");
6956 }
6957 /*
6958 * Apply additional constraints.
6959 */
6960 if (namespace != NULL) {
6961 /*
6962 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6963 * must not match the ·actual value· of the enclosing <schema>'s
6964 * targetNamespace [attribute].
6965 */
6966 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6967 xmlSchemaPCustomErr(ctxt,
6968 XML_SCHEMAP_SRC_IMPORT_1_1,
6969 NULL, NULL, node,
6970 "The value of the attribute 'namespace' must not match "
6971 "the target namespace '%s' of the importing schema",
6972 schema->targetNamespace);
6973 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6974 }
6975 } else {
6976 /*
6977 * 1.2 If the namespace [attribute] is not present, then the enclosing
6978 * <schema> must have a targetNamespace [attribute].
6979 */
6980 if (schema->targetNamespace == NULL) {
6981 xmlSchemaPCustomErr(ctxt,
6982 XML_SCHEMAP_SRC_IMPORT_1_2,
6983 NULL, NULL, node,
6984 "The attribute 'namespace' must be existent if "
6985 "the importing schema has no target namespace",
6986 NULL);
6987 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6988 }
6989 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006990 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006991 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006992 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006993 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6994 schemaLocation, &doc, &targetNamespace, 0);
6995 if (ret != 0) {
6996 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006997 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006998 return (ret);
6999 } else if (doc != NULL) {
7000 /*
7001 * Save and reset the context & schema.
7002 */
7003 url = ctxt->URL;
7004 /* TODO: Is using the doc->URL here correct? */
7005 ctxt->URL = doc->URL;
7006 flags = schema->flags;
7007 oldTNS = schema->targetNamespace;
7008 /*
7009 * Parse the schema.
7010 */
7011 root = xmlDocGetRootElement(doc);
7012 xmlSchemaClearSchemaDefaults(schema);
7013 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7014 schema->targetNamespace = targetNamespace;
7015 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7016 /*
7017 * Restore the context & schema.
7018 */
7019 schema->flags = flags;
7020 schema->targetNamespace = oldTNS;
7021 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007022 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007023
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007024 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007025}
7026
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007027/**
7028 * xmlSchemaParseInclude:
7029 * @ctxt: a schema validation context
7030 * @schema: the schema being built
7031 * @node: a subtree containing XML Schema informations
7032 *
7033 * parse a XML schema Include definition
7034 *
William M. Bracke7091952004-05-11 15:09:58 +00007035 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007036 * 1 in case of success.
7037 */
7038static int
7039xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7040 xmlNodePtr node)
7041{
7042 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007043 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007044 xmlDocPtr doc;
7045 xmlNodePtr root;
7046 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007047 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007048 xmlAttrPtr attr;
7049 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007050 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007051
7052
7053 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7054 return (-1);
7055
7056 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007057 * Check for illegal attributes.
7058 */
7059 attr = node->properties;
7060 while (attr != NULL) {
7061 if (attr->ns == NULL) {
7062 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7063 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7064 xmlSchemaPIllegalAttrErr(ctxt,
7065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7066 NULL, NULL, attr);
7067 }
7068 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7069 xmlSchemaPIllegalAttrErr(ctxt,
7070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7071 NULL, NULL, attr);
7072 }
7073 attr = attr->next;
7074 }
7075 /*
7076 * Extract and validate attributes.
7077 */
7078 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007079 * Preliminary step, extract the URI-Reference for the include and
7080 * make an URI from the base.
7081 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007082 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7083 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007084 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007085 xmlChar *uri = NULL;
7086
7087 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7088 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7089 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007090 base = xmlNodeGetBase(node->doc, node);
7091 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007092 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007093 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007094 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007095 xmlFree(base);
7096 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007097 if (uri != NULL) {
7098 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7099 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007100 }
7101 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007102 xmlSchemaPMissingAttrErr(ctxt,
7103 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7104 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007105 return (-1);
7106 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007107 /*
7108 * And now for the children...
7109 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007110 child = node->children;
7111 while (IS_SCHEMA(child, "annotation")) {
7112 /*
7113 * the annotations here are simply discarded ...
7114 */
7115 child = child->next;
7116 }
7117 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007118 xmlSchemaPContentErr(ctxt,
7119 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7120 NULL, NULL, node, child, NULL,
7121 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007122 }
7123
7124 /*
7125 * First step is to parse the input document into an DOM/Infoset
7126 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007127 /*
7128 * TODO: Use xmlCtxtReadFile to share the dictionary.
7129 */
7130 parserCtxt = xmlNewParserCtxt();
7131 if (parserCtxt == NULL) {
7132 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7133 "allocating a parser context", NULL);
7134 return(-1);
7135 }
7136
7137 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7138 xmlDictFree(parserCtxt->dict);
7139 parserCtxt->dict = ctxt->dict;
7140 xmlDictReference(parserCtxt->dict);
7141 }
7142
7143 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7144 NULL, SCHEMAS_PARSE_OPTIONS);
7145 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007146 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007147 /*
7148 * TODO: It is not an error for the ·actual value· of the
7149 * schemaLocation [attribute] to fail to resolve it all, in which
7150 * case no corresponding inclusion is performed.
7151 * So do we need a warning report here?
7152 */
7153 xmlSchemaPCustomErr(ctxt,
7154 XML_SCHEMAP_FAILED_LOAD,
7155 NULL, NULL, node,
7156 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007157 return(-1);
7158 }
7159
7160 /*
7161 * Then extract the root of the schema
7162 */
7163 root = xmlDocGetRootElement(doc);
7164 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007165 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007166 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007167 NULL, NULL, node,
7168 "The included document '%s' has no document "
7169 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007170 xmlFreeDoc(doc);
7171 return (-1);
7172 }
7173
7174 /*
7175 * Remove all the blank text nodes
7176 */
7177 xmlSchemaCleanupDoc(ctxt, root);
7178
7179 /*
7180 * Check the schemas top level element
7181 */
7182 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007183 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007184 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007185 NULL, NULL, node,
7186 "The document '%s' to be included is not a schema document",
7187 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007188 xmlFreeDoc(doc);
7189 return (-1);
7190 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007191
William M. Brack2f2a6632004-08-20 23:09:47 +00007192 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007193 /*
7194 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7195 * value· is identical to the ·actual value· of the targetNamespace
7196 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7197 */
7198 if (targetNamespace != NULL) {
7199 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007200 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007201 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007202 NULL, NULL, node,
7203 "The target namespace of the included schema "
7204 "'%s' has to be absent, since the including schema "
7205 "has no target namespace",
7206 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007207 xmlFreeDoc(doc);
7208 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007209 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7210 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007211 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007212 NULL, NULL, node,
7213 "The target namespace '%s' of the included schema '%s' "
7214 "differs from '%s' of the including schema",
7215 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007216 xmlFreeDoc(doc);
7217 return (-1);
7218 }
7219 } else if (schema->targetNamespace != NULL) {
7220 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7221 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7222 } else
7223 wasConvertingNs = 1;
7224 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007225 /*
7226 * register the include
7227 */
7228 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7229 if (include == NULL) {
7230 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7231 xmlFreeDoc(doc);
7232 return (-1);
7233 }
7234
7235 memset(include, 0, sizeof(xmlSchemaInclude));
7236 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7237 include->doc = doc;
7238 include->next = schema->includes;
7239 schema->includes = include;
7240
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007241 /*
7242 * parse the declarations in the included file like if they
7243 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007244 */
7245 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007246 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007247 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007248 /*
7249 * The default values ("blockDefault", "elementFormDefault", etc.)
7250 * are set to the values of the included schema and restored afterwards.
7251 */
7252 saveFlags = schema->flags;
7253 xmlSchemaClearSchemaDefaults(schema);
7254 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007255 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007256 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007257 /*
7258 * Remove the converting flag.
7259 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007260 if ((wasConvertingNs == 0) &&
7261 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007262 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007263 return (1);
7264}
7265
7266/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007267 * xmlSchemaParseChoice:
7268 * @ctxt: a schema validation context
7269 * @schema: the schema being built
7270 * @node: a subtree containing XML Schema informations
7271 *
7272 * parse a XML schema Choice definition
7273 * *WARNING* this interface is highly subject to change
7274 *
William M. Bracke7091952004-05-11 15:09:58 +00007275 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007276 * 1 in case of success.
7277 */
7278static xmlSchemaTypePtr
7279xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007280 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007281{
7282 xmlSchemaTypePtr type, subtype, last = NULL;
7283 xmlNodePtr child = NULL;
7284 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007285 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007286 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007287
7288 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7289 return (NULL);
7290
7291
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007292 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007293 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007294 if (type == NULL)
7295 return (NULL);
7296 type->node = node;
7297 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007298 /*
7299 * Check for illegal attributes.
7300 */
7301 attr = node->properties;
7302 while (attr != NULL) {
7303 if (attr->ns == NULL) {
7304 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7305 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7306 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7307 xmlSchemaPIllegalAttrErr(ctxt,
7308 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7309 NULL, type, attr);
7310 }
7311 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7312 xmlSchemaPIllegalAttrErr(ctxt,
7313 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7314 NULL, type, attr);
7315 }
7316 attr = attr->next;
7317 }
7318 /*
7319 * Extract and validate attributes.
7320 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007321 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007322 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7323 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7324 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007325 /*
7326 * And now for the children...
7327 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007328 oldcontainer = ctxt->container;
7329 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007330 child = node->children;
7331 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007332 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7333 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007334 }
7335 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007336 (IS_SCHEMA(child, "group")) ||
7337 (IS_SCHEMA(child, "any")) ||
7338 (IS_SCHEMA(child, "choice")) ||
7339 (IS_SCHEMA(child, "sequence"))) {
7340 subtype = NULL;
7341 if (IS_SCHEMA(child, "element")) {
7342 subtype = (xmlSchemaTypePtr)
7343 xmlSchemaParseElement(ctxt, schema, child, 0);
7344 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007345 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007346 } else if (IS_SCHEMA(child, "any")) {
7347 subtype = xmlSchemaParseAny(ctxt, schema, child);
7348 } else if (IS_SCHEMA(child, "sequence")) {
7349 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7350 } else if (IS_SCHEMA(child, "choice")) {
7351 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7352 }
7353 if (subtype != NULL) {
7354 if (last == NULL) {
7355 type->subtypes = subtype;
7356 last = subtype;
7357 } else {
7358 last->next = subtype;
7359 last = subtype;
7360 }
7361 last->next = NULL;
7362 }
7363 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007364 }
7365 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007366 /* TODO: error code. */
7367 xmlSchemaPContentErr(ctxt,
7368 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7369 NULL, type, node, child, NULL,
7370 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007371 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007372 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007373 return (type);
7374}
7375
7376/**
7377 * xmlSchemaParseSequence:
7378 * @ctxt: a schema validation context
7379 * @schema: the schema being built
7380 * @node: a subtree containing XML Schema informations
7381 *
7382 * parse a XML schema Sequence definition
7383 * *WARNING* this interface is highly subject to change
7384 *
William M. Bracke7091952004-05-11 15:09:58 +00007385 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007386 * 1 in case of success.
7387 */
7388static xmlSchemaTypePtr
7389xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007390 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007391{
7392 xmlSchemaTypePtr type, subtype, last = NULL;
7393 xmlNodePtr child = NULL;
7394 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007395 xmlAttrPtr attr;
7396 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007397
7398 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7399 return (NULL);
7400
William M. Brack2f2a6632004-08-20 23:09:47 +00007401 oldcontainer = ctxt->container;
7402 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7403 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007404 if (type == NULL)
7405 return (NULL);
7406 type->node = node;
7407 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007408 /*
7409 * Check for illegal attributes.
7410 */
7411 attr = node->properties;
7412 while (attr != NULL) {
7413 if (attr->ns == NULL) {
7414 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7415 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7416 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7417 xmlSchemaPIllegalAttrErr(ctxt,
7418 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7419 NULL, type, attr);
7420 }
7421 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7422 xmlSchemaPIllegalAttrErr(ctxt,
7423 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7424 NULL, type, attr);
7425 }
7426 attr = attr->next;
7427 }
7428 /*
7429 * Extract and validate attributes.
7430 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007431 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007432 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7433 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7434 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007435 /*
7436 * And now for the children...
7437 */
7438 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007439 child = node->children;
7440 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007441 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7442 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007443 }
7444 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007445 (IS_SCHEMA(child, "group")) ||
7446 (IS_SCHEMA(child, "any")) ||
7447 (IS_SCHEMA(child, "choice")) ||
7448 (IS_SCHEMA(child, "sequence"))) {
7449 subtype = NULL;
7450 if (IS_SCHEMA(child, "element")) {
7451 subtype = (xmlSchemaTypePtr)
7452 xmlSchemaParseElement(ctxt, schema, child, 0);
7453 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007454 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007455 } else if (IS_SCHEMA(child, "any")) {
7456 subtype = xmlSchemaParseAny(ctxt, schema, child);
7457 } else if (IS_SCHEMA(child, "choice")) {
7458 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7459 } else if (IS_SCHEMA(child, "sequence")) {
7460 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7461 }
7462 if (subtype != NULL) {
7463 if (last == NULL) {
7464 type->subtypes = subtype;
7465 last = subtype;
7466 } else {
7467 last->next = subtype;
7468 last = subtype;
7469 }
7470 last->next = NULL;
7471 }
7472 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007473 }
7474 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007475 xmlSchemaPContentErr(ctxt,
7476 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7477 NULL, type, node, child, NULL,
7478 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007479 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007480 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007481
7482 return (type);
7483}
7484
7485/**
7486 * xmlSchemaParseRestriction:
7487 * @ctxt: a schema validation context
7488 * @schema: the schema being built
7489 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007490 *
7491 * parse a XML schema Restriction definition
7492 * *WARNING* this interface is highly subject to change
7493 *
7494 * Returns the type definition or NULL in case of error
7495 */
7496static xmlSchemaTypePtr
7497xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007498 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007499{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007500 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007501 xmlNodePtr child = NULL;
7502 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007503 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007504 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007505
7506 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7507 return (NULL);
7508
7509 oldcontainer = ctxt->container;
7510
William M. Brack2f2a6632004-08-20 23:09:47 +00007511 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7512 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007513 if (type == NULL)
7514 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007515 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007516 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007517 /*
7518 * Check for illegal attributes.
7519 */
7520 attr = node->properties;
7521 while (attr != NULL) {
7522 if (attr->ns == NULL) {
7523 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7524 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7525 xmlSchemaPIllegalAttrErr(ctxt,
7526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7527 NULL, type, attr);
7528 }
7529 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7530 xmlSchemaPIllegalAttrErr(ctxt,
7531 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7532 NULL, type, attr);
7533 }
7534 attr = attr->next;
7535 }
7536 /*
7537 * Extract and validate attributes.
7538 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007539 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007540 /*
7541 * Attribute "base".
7542 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007543 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007544 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007545 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7546 /* TODO: Think about the error code. */
7547 xmlSchemaPMissingAttrErr(ctxt,
7548 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7549 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007550 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007551 /*
7552 * And now for the children...
7553 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007554 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007555 child = node->children;
7556 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007557 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7558 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007559 }
7560 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007561 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7562 if (IS_SCHEMA(child, "all")) {
7563 subtype = (xmlSchemaTypePtr)
7564 xmlSchemaParseAll(ctxt, schema, child);
7565 child = child->next;
7566 type->subtypes = subtype;
7567 } else if (IS_SCHEMA(child, "choice")) {
7568 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7569 child = child->next;
7570 type->subtypes = subtype;
7571 } else if (IS_SCHEMA(child, "sequence")) {
7572 subtype = (xmlSchemaTypePtr)
7573 xmlSchemaParseSequence(ctxt, schema, child);
7574 child = child->next;
7575 type->subtypes = subtype;
7576 } else if (IS_SCHEMA(child, "group")) {
7577 subtype = (xmlSchemaTypePtr)
7578 xmlSchemaParseGroup(ctxt, schema, child, 0);
7579 child = child->next;
7580 type->subtypes = subtype;
7581 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007582 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7583 if (IS_SCHEMA(child, "simpleType")) {
7584 if (type->base != NULL) {
7585 /*
7586 * src-restriction-base-or-simpleType
7587 * Either the base [attribute] or the simpleType [child] of the
7588 * <restriction> element must be present, but not both.
7589 */
7590 xmlSchemaPContentErr(ctxt,
7591 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7592 NULL, NULL, type->node, child,
7593 "The attribute 'base' and the <simpleType> child are "
7594 "mutually exclusive", NULL);
7595 } else {
7596 subtype = (xmlSchemaTypePtr)
7597 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7598 type->baseType = subtype;
7599 }
7600 child = child->next;
7601 }
7602 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007603 if (IS_SCHEMA(child, "simpleType")) {
7604 subtype = (xmlSchemaTypePtr)
7605 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007606 type->subtypes = subtype;
7607 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007608 }
7609 }
7610 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7611 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7612 xmlSchemaFacetPtr facet, lastfacet = NULL;
7613
Daniel Veillard01fa6152004-06-29 17:04:39 +00007614 /*
7615 * Add the facets to the parent simpleType/complexType.
7616 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007617 /*
7618 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7619 * Simple Type Definition Schema Representation Constraint:
7620 * *Single Facet Value*
7621 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007622 while ((IS_SCHEMA(child, "minInclusive")) ||
7623 (IS_SCHEMA(child, "minExclusive")) ||
7624 (IS_SCHEMA(child, "maxInclusive")) ||
7625 (IS_SCHEMA(child, "maxExclusive")) ||
7626 (IS_SCHEMA(child, "totalDigits")) ||
7627 (IS_SCHEMA(child, "fractionDigits")) ||
7628 (IS_SCHEMA(child, "pattern")) ||
7629 (IS_SCHEMA(child, "enumeration")) ||
7630 (IS_SCHEMA(child, "whiteSpace")) ||
7631 (IS_SCHEMA(child, "length")) ||
7632 (IS_SCHEMA(child, "maxLength")) ||
7633 (IS_SCHEMA(child, "minLength"))) {
7634 facet = xmlSchemaParseFacet(ctxt, schema, child);
7635 if (facet != NULL) {
7636 if (lastfacet == NULL)
7637 ctxt->ctxtType->facets = facet;
7638 else
7639 lastfacet->next = facet;
7640 lastfacet = facet;
7641 lastfacet->next = NULL;
7642 }
7643 child = child->next;
7644 }
7645 /*
7646 * Create links for derivation and validation.
7647 */
7648 if (lastfacet != NULL) {
7649 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7650
7651 facet = ctxt->ctxtType->facets;
7652 do {
7653 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7654 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007655 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007656 xmlFree(facetLink);
7657 return (NULL);
7658 }
7659 facetLink->facet = facet;
7660 facetLink->next = NULL;
7661 if (lastFacetLink == NULL)
7662 ctxt->ctxtType->facetSet = facetLink;
7663 else
7664 lastFacetLink->next = facetLink;
7665 lastFacetLink = facetLink;
7666 facet = facet->next;
7667 } while (facet != NULL);
7668 }
7669 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007670 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7671 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7672 if (IS_SCHEMA(child, "anyAttribute")) {
7673 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7674 child = child->next;
7675 }
7676 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007677 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007678 /* TODO: Think about the error code. */
7679 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7680 xmlSchemaPContentErr(ctxt,
7681 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7682 NULL, type, node, child, NULL,
7683 "annotation?, (group | all | choice | sequence)?, "
7684 "((attribute | attributeGroup)*, anyAttribute?))");
7685 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7686 xmlSchemaPContentErr(ctxt,
7687 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7688 NULL, type, node, child, NULL,
7689 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7690 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7691 "length | minLength | maxLength | enumeration | whiteSpace | "
7692 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7693 } else {
7694 /* Simple type */
7695 xmlSchemaPContentErr(ctxt,
7696 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7697 NULL, type, node, child, NULL,
7698 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7699 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7700 "length | minLength | maxLength | enumeration | whiteSpace | "
7701 "pattern)*))");
7702 }
7703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007704 ctxt->container = oldcontainer;
7705 return (type);
7706}
7707
7708/**
7709 * xmlSchemaParseExtension:
7710 * @ctxt: a schema validation context
7711 * @schema: the schema being built
7712 * @node: a subtree containing XML Schema informations
7713 *
7714 * parse a XML schema Extension definition
7715 * *WARNING* this interface is highly subject to change
7716 *
7717 * Returns the type definition or NULL in case of error
7718 */
7719static xmlSchemaTypePtr
7720xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007721 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007722{
7723 xmlSchemaTypePtr type, subtype;
7724 xmlNodePtr child = NULL;
7725 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007726 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007727
7728 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7729 return (NULL);
7730
7731 oldcontainer = ctxt->container;
7732
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007733 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007734 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007735 if (type == NULL)
7736 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007737 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007738 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007739 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007740 ctxt->container = name;
7741
7742 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7743 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007744 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007745 "<extension>: The attribute \"base\" is missing.\n",
7746 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007747 }
7748 child = node->children;
7749 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007750 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7751 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007752 }
7753 subtype = NULL;
7754
7755 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007756 subtype = xmlSchemaParseAll(ctxt, schema, child);
7757 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007758 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007759 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7760 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007761 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007762 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7763 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007764 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007765 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007766 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007767 }
7768 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007769 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007770 if ((ctxt->ctxtType != NULL) &&
7771 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7772 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7773 if (IS_SCHEMA(child, "anyAttribute")) {
7774 ctxt->ctxtType->attributeWildcard =
7775 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7776 child = child->next;
7777 }
7778 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007779 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007780 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007781 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7782 "<extension> has unexpected content.\n", type->name,
7783 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007784 }
7785 ctxt->container = oldcontainer;
7786 return (type);
7787}
7788
7789/**
7790 * xmlSchemaParseSimpleContent:
7791 * @ctxt: a schema validation context
7792 * @schema: the schema being built
7793 * @node: a subtree containing XML Schema informations
7794 *
7795 * parse a XML schema SimpleContent definition
7796 * *WARNING* this interface is highly subject to change
7797 *
7798 * Returns the type definition or NULL in case of error
7799 */
7800static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007801xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7802 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007803{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007804 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007805 xmlNodePtr child = NULL;
7806 xmlChar name[30];
7807
7808 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7809 return (NULL);
7810
William M. Bracke7091952004-05-11 15:09:58 +00007811 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007812 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007813 if (type == NULL)
7814 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007815 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007816 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007817 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007818
7819 child = node->children;
7820 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007821 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7822 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007823 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007824 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007825 ctxt->parentItem = type;
7826 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007827 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007828 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007829 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007830 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007831 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007832 subtype = (xmlSchemaTypePtr)
7833 xmlSchemaParseExtension(ctxt, schema, child);
7834 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007835 }
7836 type->subtypes = subtype;
7837 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007838 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007839 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7840 "<simpleContent> has unexpected content.\n",
7841 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007842 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007843 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007844 return (type);
7845}
7846
7847/**
7848 * xmlSchemaParseComplexContent:
7849 * @ctxt: a schema validation context
7850 * @schema: the schema being built
7851 * @node: a subtree containing XML Schema informations
7852 *
7853 * parse a XML schema ComplexContent definition
7854 * *WARNING* this interface is highly subject to change
7855 *
7856 * Returns the type definition or NULL in case of error
7857 */
7858static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007859xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7860 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007861{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007862 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007863 xmlNodePtr child = NULL;
7864 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007865 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007866
7867 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7868 return (NULL);
7869
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007870 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007871 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007872 if (type == NULL)
7873 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007874 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007875 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007876 /*
7877 * Check for illegal attributes.
7878 */
7879 attr = node->properties;
7880 while (attr != NULL) {
7881 if (attr->ns == NULL) {
7882 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7883 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7884 {
7885 xmlSchemaPIllegalAttrErr(ctxt,
7886 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7887 NULL, NULL, attr);
7888 }
7889 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7890 xmlSchemaPIllegalAttrErr(ctxt,
7891 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7892 NULL, NULL, attr);
7893 }
7894 attr = attr->next;
7895 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007896 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007897 /*
7898 * Handle attribute 'mixed'.
7899 */
7900 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7901 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7902 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7903 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007904 child = node->children;
7905 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007906 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7907 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007908 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007909 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007910 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007911 subtype = NULL;
7912 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007913 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007914 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007915 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007916 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007917 subtype = (xmlSchemaTypePtr)
7918 xmlSchemaParseExtension(ctxt, schema, child);
7919 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007920 }
7921 type->subtypes = subtype;
7922 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007923 xmlSchemaPContentErr(ctxt,
7924 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7925 NULL, NULL, node, child,
7926 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007927 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007928 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007929 return (type);
7930}
7931
7932/**
7933 * xmlSchemaParseComplexType:
7934 * @ctxt: a schema validation context
7935 * @schema: the schema being built
7936 * @node: a subtree containing XML Schema informations
7937 *
7938 * parse a XML schema Complex Type definition
7939 * *WARNING* this interface is highly subject to change
7940 *
7941 * Returns the type definition or NULL in case of error
7942 */
7943static xmlSchemaTypePtr
7944xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007945 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007946{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007947 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007948 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007949 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007950 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007951 xmlAttrPtr attr;
7952 const xmlChar *attrValue;
7953 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007954 char buf[40];
7955
Daniel Veillard4255d502002-04-16 15:50:10 +00007956
7957 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7958 return (NULL);
7959
Daniel Veillard01fa6152004-06-29 17:04:39 +00007960 ctxtType = ctxt->ctxtType;
7961
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007962 if (topLevel) {
7963 attr = xmlSchemaGetPropNode(node, "name");
7964 if (attr == NULL) {
7965 xmlSchemaPMissingAttrErr(ctxt,
7966 XML_SCHEMAP_S4S_ATTR_MISSING,
7967 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7968 "name", NULL);
7969 return (NULL);
7970 } else if (xmlSchemaPValAttrNode(ctxt,
7971 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7972 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7973 return (NULL);
7974 }
7975 }
7976
7977 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007978 /*
7979 * Parse as local complex type definition.
7980 */
7981 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7982 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7983 if (type == NULL)
7984 return (NULL);
7985 name = (const xmlChar *) buf;
7986 type->node = node;
7987 type->type = XML_SCHEMA_TYPE_COMPLEX;
7988 /*
7989 * TODO: We need the target namespace.
7990 */
7991 } else {
7992 /*
7993 * Parse as global complex type definition.
7994 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007995 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007996 if (type == NULL)
7997 return (NULL);
7998 type->node = node;
7999 type->type = XML_SCHEMA_TYPE_COMPLEX;
8000 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8001 /*
8002 * Set defaults.
8003 */
8004 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8005 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008006 }
8007 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008008 /*
8009 * Handle attributes.
8010 */
8011 attr = node->properties;
8012 while (attr != NULL) {
8013 if (attr->ns == NULL) {
8014 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8015 /*
8016 * Attribute "id".
8017 */
8018 type->id = xmlSchemaGetProp(ctxt, node, "id");
8019 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8020 /*
8021 * Attribute "mixed".
8022 */
8023 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8024 (xmlNodePtr) attr))
8025 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8026 } else if (topLevel) {
8027 /*
8028 * Attributes of global complex type definitions.
8029 */
8030 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8031 /* Pass. */
8032 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8033 /*
8034 * Attribute "abstract".
8035 */
8036 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8037 (xmlNodePtr) attr))
8038 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8039 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8040 /*
8041 * Attribute "final".
8042 */
8043 attrValue = xmlSchemaGetNodeContent(ctxt,
8044 (xmlNodePtr) attr);
8045 if (xmlSchemaPValAttrBlockFinal(attrValue,
8046 &(type->flags),
8047 -1,
8048 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8049 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8050 -1, -1, -1) != 0)
8051 {
8052 xmlSchemaPSimpleTypeErr(ctxt,
8053 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8054 &des, type, (xmlNodePtr) attr,
8055 NULL,
8056 "(#all | List of (extension | restriction))",
8057 attrValue, NULL, NULL, NULL);
8058 }
8059 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8060 /*
8061 * Attribute "block".
8062 */
8063 attrValue = xmlSchemaGetNodeContent(ctxt,
8064 (xmlNodePtr) attr);
8065 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8066 -1,
8067 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8068 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8069 -1, -1, -1) != 0) {
8070 xmlSchemaPSimpleTypeErr(ctxt,
8071 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8072 &des, type, (xmlNodePtr) attr,
8073 NULL,
8074 "(#all | List of (extension | restriction)) ",
8075 attrValue, NULL, NULL, NULL);
8076 }
8077 } else {
8078 xmlSchemaPIllegalAttrErr(ctxt,
8079 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8080 &des, type, attr);
8081 }
8082 } else {
8083 xmlSchemaPIllegalAttrErr(ctxt,
8084 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8085 &des, type, attr);
8086 }
8087 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8088 xmlSchemaPIllegalAttrErr(ctxt,
8089 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8090 &des, type, attr);
8091 }
8092 attr = attr->next;
8093 }
8094 /*
8095 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008096 * This will be only changed if a complex type
8097 * inherits an attribute wildcard from a base type.
8098 */
8099 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008100 /*
8101 * And now for the children...
8102 */
8103 oldcontainer = ctxt->container;
8104 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008105 child = node->children;
8106 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008107 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8108 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008109 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008110 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008111 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008112 /*
8113 * 3.4.3 : 2.2
8114 * Specifying mixed='true' when the <simpleContent>
8115 * alternative is chosen has no effect
8116 */
William M. Bracke7091952004-05-11 15:09:58 +00008117 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8118 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008119 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8120 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008121 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008122 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8123 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008124 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008125 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008126 /*
8127 * Parse model groups.
8128 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008129 if (IS_SCHEMA(child, "all")) {
8130 subtype = xmlSchemaParseAll(ctxt, schema, child);
8131 child = child->next;
8132 } else if (IS_SCHEMA(child, "choice")) {
8133 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8134 child = child->next;
8135 } else if (IS_SCHEMA(child, "sequence")) {
8136 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8137 child = child->next;
8138 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008139 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008140 child = child->next;
8141 }
8142 if (subtype != NULL)
8143 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008144 /*
8145 * Parse attribute decls/refs.
8146 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008147 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008148 /*
8149 * Parse attribute wildcard.
8150 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008151 if (IS_SCHEMA(child, "anyAttribute")) {
8152 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8153 child = child->next;
8154 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008155 }
8156 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008157 xmlSchemaPContentErr(ctxt,
8158 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8159 &des, type, node, child,
8160 NULL, "(annotation?, (simpleContent | complexContent | "
8161 "((group | all | choice | sequence)?, ((attribute | "
8162 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008163 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008164 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008165 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008166 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008167 return (type);
8168}
8169
Daniel Veillard4255d502002-04-16 15:50:10 +00008170/**
8171 * xmlSchemaParseSchema:
8172 * @ctxt: a schema validation context
8173 * @node: a subtree containing XML Schema informations
8174 *
8175 * parse a XML schema definition from a node set
8176 * *WARNING* this interface is highly subject to change
8177 *
8178 * Returns the internal XML Schema structure built from the resource or
8179 * NULL in case of error
8180 */
8181static xmlSchemaPtr
8182xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8183{
8184 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008185 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008186 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008187 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008188
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008189 /*
8190 * This one is called by xmlSchemaParse only and is used if
8191 * the schema to be parsed was specified via the API; i.e. not
8192 * automatically by the validated instance document.
8193 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008194 if ((ctxt == NULL) || (node == NULL))
8195 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008196 nberrors = ctxt->nberrors;
8197 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008198 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008199 xmlSchemaImportPtr import;
8200
Daniel Veillard4255d502002-04-16 15:50:10 +00008201 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008202 if (schema == NULL)
8203 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008204 /*
8205 * Disable build of list of items.
8206 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008207 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8208 if (attr != NULL) {
8209 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8210 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8211 /*
8212 * TODO: Should we proceed with an invalid target namespace?
8213 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008214 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8215 } else {
8216 schema->targetNamespace = NULL;
8217 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008218 /*
8219 * Add the current ns name and location to the import table;
8220 * this is needed to have a consistent mechanism, regardless
8221 * if all schemata are constructed dynamically fired by the
8222 * instance or if the schema to be used was specified via
8223 * the API.
8224 */
8225 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8226 schema->targetNamespace);
8227 if (import == NULL) {
8228 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8229 NULL, NULL, (xmlNodePtr) ctxt->doc,
8230 "Internal error: xmlSchemaParseSchema, "
8231 "failed to add an import entry", NULL);
8232 xmlSchemaFree(schema);
8233 schema = NULL;
8234 return (NULL);
8235 }
8236 import->schemaLocation = ctxt->URL;
8237 /*
8238 * NOTE: We won't set the doc here, otherwise it will be freed
8239 * if the import struct is freed.
8240 * import->doc = ctxt->doc;
8241 */
8242
Daniel Veillardc0826a72004-08-10 14:17:33 +00008243 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008244 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008245 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8246 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8247
William M. Brack2f2a6632004-08-20 23:09:47 +00008248 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008249 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8250 } else {
8251 xmlDocPtr doc;
8252
8253 doc = node->doc;
8254
8255 if ((doc != NULL) && (doc->URL != NULL)) {
8256 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8257 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008258 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008259 } else {
8260 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8261 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008262 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008263 }
8264 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008265 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008266 if (ctxt->nberrors != 0) {
8267 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008268 xmlSchemaFree(schema);
8269 schema = NULL;
8270 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008271 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008272 if (schema != NULL)
8273 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008274 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008275#ifdef DEBUG
8276 if (schema == NULL)
8277 xmlGenericError(xmlGenericErrorContext,
8278 "xmlSchemaParse() failed\n");
8279#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008280 return (schema);
8281}
8282
8283/************************************************************************
8284 * *
8285 * Validating using Schemas *
8286 * *
8287 ************************************************************************/
8288
8289/************************************************************************
8290 * *
8291 * Reading/Writing Schemas *
8292 * *
8293 ************************************************************************/
8294
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008295#if 0 /* Will be enabled if it is clear what options are needed. */
8296/**
8297 * xmlSchemaParserCtxtSetOptions:
8298 * @ctxt: a schema parser context
8299 * @options: a combination of xmlSchemaParserOption
8300 *
8301 * Sets the options to be used during the parse.
8302 *
8303 * Returns 0 in case of success, -1 in case of an
8304 * API error.
8305 */
8306static int
8307xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8308 int options)
8309
8310{
8311 int i;
8312
8313 if (ctxt == NULL)
8314 return (-1);
8315 /*
8316 * WARNING: Change the start value if adding to the
8317 * xmlSchemaParseOption.
8318 */
8319 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8320 if (options & 1<<i) {
8321 return (-1);
8322 }
8323 }
8324 ctxt->options = options;
8325 return (0);
8326}
8327
8328/**
8329 * xmlSchemaValidCtxtGetOptions:
8330 * @ctxt: a schema parser context
8331 *
8332 * Returns the option combination of the parser context.
8333 */
8334static int
8335xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8336
8337{
8338 if (ctxt == NULL)
8339 return (-1);
8340 else
8341 return (ctxt->options);
8342}
8343
8344 void *curItems; /* used for dynamic addition of schemata */
8345 int nbCurItems; /* used for dynamic addition of schemata */
8346 int sizeCurItems; /* used for dynamic addition of schemata */
8347
8348#endif
8349
Daniel Veillard4255d502002-04-16 15:50:10 +00008350/**
8351 * xmlSchemaNewParserCtxt:
8352 * @URL: the location of the schema
8353 *
8354 * Create an XML Schemas parse context for that file/resource expected
8355 * to contain an XML Schemas file.
8356 *
8357 * Returns the parser context or NULL in case of error
8358 */
8359xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008360xmlSchemaNewParserCtxt(const char *URL)
8361{
Daniel Veillard4255d502002-04-16 15:50:10 +00008362 xmlSchemaParserCtxtPtr ret;
8363
8364 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008365 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008366
8367 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8368 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008369 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008370 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008371 return (NULL);
8372 }
8373 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008374 ret->dict = xmlDictCreate();
8375 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008376 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008377 return (ret);
8378}
8379
8380/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008381 * xmlSchemaNewParserCtxtUseDict:
8382 * @URL: the location of the schema
8383 * @dict: the dictionary to be used
8384 *
8385 * Create an XML Schemas parse context for that file/resource expected
8386 * to contain an XML Schemas file.
8387 *
8388 * Returns the parser context or NULL in case of error
8389 */
8390static xmlSchemaParserCtxtPtr
8391xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8392{
8393 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008394 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008395 if (URL == NULL)
8396 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008397 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008398
8399 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8400 if (ret == NULL) {
8401 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8402 NULL);
8403 return (NULL);
8404 }
8405 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8406 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008407 xmlDictReference(dict);
8408 if (URL != NULL)
8409 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008410 ret->includes = 0;
8411 return (ret);
8412}
8413
8414
8415/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008416 * xmlSchemaNewMemParserCtxt:
8417 * @buffer: a pointer to a char array containing the schemas
8418 * @size: the size of the array
8419 *
8420 * Create an XML Schemas parse context for that memory buffer expected
8421 * to contain an XML Schemas file.
8422 *
8423 * Returns the parser context or NULL in case of error
8424 */
8425xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008426xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8427{
Daniel Veillard6045c902002-10-09 21:13:59 +00008428 xmlSchemaParserCtxtPtr ret;
8429
8430 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008431 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008432
8433 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8434 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008435 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008436 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008437 return (NULL);
8438 }
8439 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8440 ret->buffer = buffer;
8441 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008442 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008443 return (ret);
8444}
8445
8446/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008447 * xmlSchemaNewDocParserCtxt:
8448 * @doc: a preparsed document tree
8449 *
8450 * Create an XML Schemas parse context for that document.
8451 * NB. The document may be modified during the parsing process.
8452 *
8453 * Returns the parser context or NULL in case of error
8454 */
8455xmlSchemaParserCtxtPtr
8456xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8457{
8458 xmlSchemaParserCtxtPtr ret;
8459
8460 if (doc == NULL)
8461 return (NULL);
8462
8463 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8464 if (ret == NULL) {
8465 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8466 NULL);
8467 return (NULL);
8468 }
8469 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8470 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008471 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008472 /* The application has responsibility for the document */
8473 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008474
8475 return (ret);
8476}
8477
8478/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008479 * xmlSchemaFreeParserCtxt:
8480 * @ctxt: the schema parser context
8481 *
8482 * Free the resources associated to the schema parser context
8483 */
8484void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008485xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8486{
Daniel Veillard4255d502002-04-16 15:50:10 +00008487 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008488 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008489 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008490 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008491 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008492 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008493 xmlFree(ctxt->assemble);
8494 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008495 if (ctxt->vctxt != NULL) {
8496 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8497 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008498 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008499 xmlFree(ctxt);
8500}
8501
8502/************************************************************************
8503 * *
8504 * Building the content models *
8505 * *
8506 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008507
Daniel Veillard4255d502002-04-16 15:50:10 +00008508/**
8509 * xmlSchemaBuildAContentModel:
8510 * @type: the schema type definition
8511 * @ctxt: the schema parser context
8512 * @name: the element name whose content is being built
8513 *
8514 * Generate the automata sequence needed for that type
8515 */
8516static void
8517xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008518 xmlSchemaParserCtxtPtr ctxt,
8519 const xmlChar * name)
8520{
Daniel Veillard4255d502002-04-16 15:50:10 +00008521 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008522 xmlGenericError(xmlGenericErrorContext,
8523 "Found unexpected type = NULL in %s content model\n",
8524 name);
8525 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008526 }
8527 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008528 case XML_SCHEMA_TYPE_ANY: {
8529 xmlAutomataStatePtr start, end;
8530 xmlSchemaWildcardPtr wild;
8531 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008532
Daniel Veillardc0826a72004-08-10 14:17:33 +00008533 wild = type->attributeWildcard;
8534
8535 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008536 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008537 "Internal error: xmlSchemaBuildAContentModel, "
8538 "no wildcard on xsd:any.\n", NULL, NULL);
8539 return;
8540 }
8541
8542 start = ctxt->state;
8543 end = xmlAutomataNewState(ctxt->am);
8544
8545 if (type->maxOccurs == 1) {
8546 if (wild->any == 1) {
8547 /*
8548 * We need to add both transitions:
8549 *
8550 * 1. the {"*", "*"} for elements in a namespace.
8551 */
8552 ctxt->state =
8553 xmlAutomataNewTransition2(ctxt->am,
8554 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8555 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8556 /*
8557 * 2. the {"*"} for elements in no namespace.
8558 */
8559 ctxt->state =
8560 xmlAutomataNewTransition2(ctxt->am,
8561 start, NULL, BAD_CAST "*", NULL, type);
8562 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8563
8564 } else if (wild->nsSet != NULL) {
8565 ns = wild->nsSet;
8566 do {
8567 ctxt->state = start;
8568 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8569 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8570 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8571 ns = ns->next;
8572 } while (ns != NULL);
8573
8574 } else if (wild->negNsSet != NULL) {
8575 xmlAutomataStatePtr deadEnd;
8576
8577 deadEnd = xmlAutomataNewState(ctxt->am);
8578 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8579 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8580 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8581 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8582 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8583 }
8584 } else {
8585 int counter;
8586 xmlAutomataStatePtr hop;
8587 int maxOccurs =
8588 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8589 int minOccurs =
8590 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8591
8592 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8593 hop = xmlAutomataNewState(ctxt->am);
8594 if (wild->any == 1) {
8595 ctxt->state =
8596 xmlAutomataNewTransition2(ctxt->am,
8597 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8598 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8599 ctxt->state =
8600 xmlAutomataNewTransition2(ctxt->am,
8601 start, NULL, BAD_CAST "*", NULL, type);
8602 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8603 } else if (wild->nsSet != NULL) {
8604 ns = wild->nsSet;
8605 do {
8606 ctxt->state =
8607 xmlAutomataNewTransition2(ctxt->am,
8608 start, NULL, BAD_CAST "*", ns->value, type);
8609 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8610 ns = ns->next;
8611 } while (ns != NULL);
8612
8613 } else if (wild->negNsSet != NULL) {
8614 xmlAutomataStatePtr deadEnd;
8615
8616 deadEnd = xmlAutomataNewState(ctxt->am);
8617 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8618 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8619 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8620 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8621 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8622 }
8623 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8624 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8625 }
8626 if (type->minOccurs == 0) {
8627 xmlAutomataNewEpsilon(ctxt->am, start, end);
8628 }
8629 ctxt->state = end;
8630 break;
8631 }
8632 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008633 xmlAutomataStatePtr oldstate;
8634 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008635
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008636 /*
8637 * IMPORTANT: This puts element declarations
8638 * (and never element decl. references) into the
8639 * automaton. This is crucial and should not be changed,
8640 * since validating functions rely now on it.
8641 */
8642 particle = (xmlSchemaElementPtr) type;
8643 if (particle->ref != NULL) {
8644 if (particle->refDecl == NULL) {
8645 /*
8646 * Skip content model creation if the reference
8647 * did not resolve to a declaration.
8648 */
8649 break;
8650 } else {
8651 /*
8652 * Referenced global element declaration.
8653 */
8654 elemDecl = particle->refDecl;
8655 }
8656 } else {
8657 /*
8658 * Anonymous element declaration.
8659 */
8660 elemDecl = particle;
8661 }
8662
8663 oldstate = ctxt->state;
8664
8665 if (particle->maxOccurs >= UNBOUNDED) {
8666 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008667 xmlAutomataStatePtr tmp;
8668 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008669
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008670 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008671 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008672 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008673 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008674 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00008675 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008676 xmlAutomataNewTransition2(ctxt->am,
8677 ctxt->state, NULL,
8678 elemDecl->name,
8679 elemDecl->targetNamespace,
8680 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008681 tmp = ctxt->state;
8682 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008683 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008684 ctxt->state =
8685 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008686 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008687
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008688 } else {
8689 ctxt->state =
8690 xmlAutomataNewTransition2(ctxt->am,
8691 ctxt->state, NULL,
8692 elemDecl->name,
8693 elemDecl->targetNamespace,
8694 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008695 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8696 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008697 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008698 /* basically an elem* */
8699 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8700 ctxt->state);
8701 }
8702 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008703 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008704 xmlAutomataStatePtr tmp;
8705 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008707 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8708 oldstate, NULL);
8709 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008710 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008711 particle->minOccurs - 1,
8712 particle->maxOccurs - 1);
8713 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8714 ctxt->state,
8715 NULL,
8716 elemDecl->name,
8717 elemDecl->targetNamespace,
8718 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008719 tmp = ctxt->state;
8720 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008721 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008722 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008723 NULL, counter);
8724 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008725 /* basically an elem? */
8726 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008727 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008728 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008729
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008730 } else {
8731 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8732 ctxt->state,
8733 NULL,
8734 elemDecl->name,
8735 elemDecl->targetNamespace,
8736 (xmlSchemaTypePtr) elemDecl);
8737 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008738 /* basically an elem? */
8739 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008740 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008741 }
8742 }
8743 break;
8744 }
8745 case XML_SCHEMA_TYPE_SEQUENCE:{
8746 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008747
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008748 /*
8749 * If max and min occurances are default (1) then
8750 * simply iterate over the subtypes
8751 */
8752 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8753 subtypes = type->subtypes;
8754 while (subtypes != NULL) {
8755 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8756 subtypes = subtypes->next;
8757 }
8758 } else {
8759 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008760
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008761 if (type->maxOccurs >= UNBOUNDED) {
8762 if (type->minOccurs > 1) {
8763 xmlAutomataStatePtr tmp;
8764 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008765
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008766 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8767 oldstate,
8768 NULL);
8769 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008770
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008771 counter = xmlAutomataNewCounter(ctxt->am,
8772 type->
8773 minOccurs - 1,
8774 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008775
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008776 subtypes = type->subtypes;
8777 while (subtypes != NULL) {
8778 xmlSchemaBuildAContentModel(subtypes, ctxt,
8779 name);
8780 subtypes = subtypes->next;
8781 }
8782 tmp = ctxt->state;
8783 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8784 oldstate, counter);
8785 ctxt->state =
8786 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8787 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008788
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008789 } else {
8790 subtypes = type->subtypes;
8791 while (subtypes != NULL) {
8792 xmlSchemaBuildAContentModel(subtypes, ctxt,
8793 name);
8794 subtypes = subtypes->next;
8795 }
8796 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8797 oldstate);
8798 if (type->minOccurs == 0) {
8799 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8800 ctxt->state);
8801 }
8802 }
8803 } else if ((type->maxOccurs > 1)
8804 || (type->minOccurs > 1)) {
8805 xmlAutomataStatePtr tmp;
8806 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008807
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008808 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8809 oldstate,
8810 NULL);
8811 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008812
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008813 counter = xmlAutomataNewCounter(ctxt->am,
8814 type->minOccurs -
8815 1,
8816 type->maxOccurs -
8817 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008818
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008819 subtypes = type->subtypes;
8820 while (subtypes != NULL) {
8821 xmlSchemaBuildAContentModel(subtypes, ctxt,
8822 name);
8823 subtypes = subtypes->next;
8824 }
8825 tmp = ctxt->state;
8826 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8827 counter);
8828 ctxt->state =
8829 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8830 counter);
8831 if (type->minOccurs == 0) {
8832 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8833 ctxt->state);
8834 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008835
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008836 } else {
8837 subtypes = type->subtypes;
8838 while (subtypes != NULL) {
8839 xmlSchemaBuildAContentModel(subtypes, ctxt,
8840 name);
8841 subtypes = subtypes->next;
8842 }
8843 if (type->minOccurs == 0) {
8844 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8845 ctxt->state);
8846 }
8847 }
8848 }
8849 break;
8850 }
8851 case XML_SCHEMA_TYPE_CHOICE:{
8852 xmlSchemaTypePtr subtypes;
8853 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008854
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008855 start = ctxt->state;
8856 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008857
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008858 /*
8859 * iterate over the subtypes and remerge the end with an
8860 * epsilon transition
8861 */
8862 if (type->maxOccurs == 1) {
8863 subtypes = type->subtypes;
8864 while (subtypes != NULL) {
8865 ctxt->state = start;
8866 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8867 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8868 subtypes = subtypes->next;
8869 }
8870 } else {
8871 int counter;
8872 xmlAutomataStatePtr hop;
8873 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8874 UNBOUNDED : type->maxOccurs - 1;
8875 int minOccurs =
8876 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008877
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008878 /*
8879 * use a counter to keep track of the number of transtions
8880 * which went through the choice.
8881 */
8882 counter =
8883 xmlAutomataNewCounter(ctxt->am, minOccurs,
8884 maxOccurs);
8885 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008886
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008887 subtypes = type->subtypes;
8888 while (subtypes != NULL) {
8889 ctxt->state = start;
8890 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8891 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8892 subtypes = subtypes->next;
8893 }
8894 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8895 counter);
8896 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8897 counter);
8898 }
8899 if (type->minOccurs == 0) {
8900 xmlAutomataNewEpsilon(ctxt->am, start, end);
8901 }
8902 ctxt->state = end;
8903 break;
8904 }
8905 case XML_SCHEMA_TYPE_ALL:{
8906 xmlAutomataStatePtr start;
8907 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008908
Daniel Veillard3646d642004-06-02 19:19:14 +00008909 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008910 int lax;
8911
8912 subtypes = type->subtypes;
8913 if (subtypes == NULL)
8914 break;
8915 start = ctxt->state;
8916 while (subtypes != NULL) {
8917 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008918 /*
8919 * the following 'if' was needed to fix bug 139897
8920 * not quite sure why it only needs to be done for
8921 * elements with a 'ref', but it seems to work ok.
8922 */
8923 if (subtypes->ref != NULL)
8924 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008925 elem = (xmlSchemaElementPtr) subtypes;
8926 /*
8927 * NOTE: The {max occurs} of all the particles in the
8928 * {particles} of the group must be 0 or 1.
8929 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008930 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008931 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8932 ctxt->state,
8933 elem->name,
8934 elem->targetNamespace,
8935 1, 1, subtypes);
8936 } else if ((elem->minOccurs == 0) &&
8937 (elem->maxOccurs == 1)) {
8938
8939 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8940 ctxt->state,
8941 elem->name,
8942 elem->targetNamespace,
8943 0,
8944 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008945 subtypes);
8946 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008947 /*
8948 * NOTE: if maxOccurs == 0 then no transition will be
8949 * created.
8950 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008951 subtypes = subtypes->next;
8952 }
8953 lax = type->minOccurs == 0;
8954 ctxt->state =
8955 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8956 lax);
8957 break;
8958 }
8959 case XML_SCHEMA_TYPE_RESTRICTION:
8960 if (type->subtypes != NULL)
8961 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8962 break;
8963 case XML_SCHEMA_TYPE_EXTENSION:
8964 if (type->baseType != NULL) {
8965 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008966
8967 /*
8968 * TODO: Circular definitions will be checked at the
8969 * constraint level. So remove this when the complex type
8970 * constraints are implemented.
8971 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008972 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008973 /* TODO: Change the error code. */
8974 xmlSchemaPCustomErr(ctxt,
8975 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8976 NULL, type, type->node,
8977 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008978 return;
8979 }
8980 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008981 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008982 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008983 subtypes = type->subtypes;
8984 while (subtypes != NULL) {
8985 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8986 subtypes = subtypes->next;
8987 }
8988 } else if (type->subtypes != NULL)
8989 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8990 break;
8991 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008992 /*
8993 * Handle model group definition references.
8994 * NOTE: type->subtypes is the referenced model grop definition;
8995 * and type->subtypes->subtypes is the model group (i.e. <all> or
8996 * <choice> or <sequence>).
8997 */
8998 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8999 (type->subtypes->subtypes != NULL)) {
9000 xmlSchemaTypePtr modelGr;
9001 xmlAutomataStatePtr start, end;
9002
9003 modelGr = type->subtypes->subtypes;
9004 start = ctxt->state;
9005 end = xmlAutomataNewState(ctxt->am);
9006 if (type->maxOccurs == 1) {
9007 ctxt->state = start;
9008 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9009 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9010 } else {
9011 int counter;
9012 xmlAutomataStatePtr hop;
9013 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9014 UNBOUNDED : type->maxOccurs - 1;
9015 int minOccurs =
9016 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9017
9018 counter =
9019 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9020 hop = xmlAutomataNewState(ctxt->am);
9021 ctxt->state = start;
9022 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9023 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9024 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9025 counter);
9026 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9027 counter);
9028 }
9029 if (type->minOccurs == 0) {
9030 xmlAutomataNewEpsilon(ctxt->am, start, end);
9031 }
9032 ctxt->state = end;
9033 break;
9034 }
9035 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009036 case XML_SCHEMA_TYPE_COMPLEX:
9037 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9038 if (type->subtypes != NULL)
9039 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9040 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009041 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9042 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009043 default:
9044 xmlGenericError(xmlGenericErrorContext,
9045 "Found unexpected type %d in %s content model\n",
9046 type->type, name);
9047 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009048 }
9049}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009050
Daniel Veillard4255d502002-04-16 15:50:10 +00009051/**
9052 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009053 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009054 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009055 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009056 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009057 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009058 */
9059static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009060xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009061 xmlSchemaParserCtxtPtr ctxt,
9062 const xmlChar * name)
9063{
Daniel Veillard4255d502002-04-16 15:50:10 +00009064 xmlAutomataStatePtr start;
9065
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009066 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9067 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9068 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9069 (type->contModel != NULL))
9070 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009071
9072#ifdef DEBUG_CONTENT
9073 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009074 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009075#endif
9076
Daniel Veillard4255d502002-04-16 15:50:10 +00009077 ctxt->am = xmlNewAutomata();
9078 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009079 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009080 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009081 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009082 }
9083 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009084 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009085 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009086 type->contModel = xmlAutomataCompile(ctxt->am);
9087 if (type->contModel == NULL) {
9088 xmlSchemaPCustomErr(ctxt,
9089 XML_SCHEMAP_INTERNAL,
9090 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009091 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009092 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009093 xmlSchemaPCustomErr(ctxt,
9094 XML_SCHEMAP_NOT_DETERMINISTIC,
9095 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009096 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009097 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009098 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009099#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009100 xmlGenericError(xmlGenericErrorContext,
9101 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009102 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009103#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009104 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009105 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009106 xmlFreeAutomata(ctxt->am);
9107 ctxt->am = NULL;
9108}
9109
9110/**
9111 * xmlSchemaRefFixupCallback:
9112 * @elem: the schema element context
9113 * @ctxt: the schema parser context
9114 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009115 * Resolves the references of an element declaration
9116 * or particle, which has an element declaration as it's
9117 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009118 */
9119static void
9120xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009121 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009122 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009123 const xmlChar * context ATTRIBUTE_UNUSED,
9124 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009125{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009126 if ((ctxt == NULL) || (elem == NULL) ||
9127 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009128 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009129 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009130 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009131 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009132
Daniel Veillardc0826a72004-08-10 14:17:33 +00009133 /*
9134 * TODO: Evaluate, what errors could occur if the declaration is not
9135 * found. It might be possible that the "typefixup" might crash if
9136 * no ref declaration was found.
9137 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009138 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009139 if (elemDecl == NULL) {
9140 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009141 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009142 NULL, (xmlSchemaTypePtr) elem, elem->node,
9143 "ref", elem->ref, elem->refNs,
9144 XML_SCHEMA_TYPE_ELEMENT, NULL);
9145 } else
9146 elem->refDecl = elemDecl;
9147 } else {
9148 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9149 xmlSchemaTypePtr type;
9150
9151 /* (type definition) ... otherwise the type definition ·resolved·
9152 * to by the ·actual value· of the type [attribute] ...
9153 */
9154 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9155 elem->namedTypeNs);
9156 if (type == NULL) {
9157 xmlSchemaPResCompAttrErr(ctxt,
9158 XML_SCHEMAP_SRC_RESOLVE,
9159 NULL, (xmlSchemaTypePtr) elem, elem->node,
9160 "type", elem->namedType, elem->namedTypeNs,
9161 XML_SCHEMA_TYPE_BASIC, "type definition");
9162 } else
9163 elem->subtypes = type;
9164 }
9165 if (elem->substGroup != NULL) {
9166 xmlSchemaElementPtr substHead;
9167
9168 /*
9169 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9170 * substitutionGroup?
9171 */
9172 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009173 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009174 if (substHead == NULL) {
9175 xmlSchemaPResCompAttrErr(ctxt,
9176 XML_SCHEMAP_SRC_RESOLVE,
9177 NULL, (xmlSchemaTypePtr) elem, NULL,
9178 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9179 XML_SCHEMA_TYPE_ELEMENT, NULL);
9180 } else {
9181 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9182 /*
9183 * (type definition)...otherwise the {type definition} of the
9184 * element declaration ·resolved· to by the ·actual value· of
9185 * the substitutionGroup [attribute], if present
9186 */
9187 if (elem->subtypes == NULL)
9188 elem->subtypes = substHead->subtypes;
9189 }
9190 }
9191 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9192 (elem->substGroup == NULL))
9193 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9194 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009195}
9196
William M. Bracke7091952004-05-11 15:09:58 +00009197/**
9198 * xmlSchemaParseListRefFixup:
9199 * @type: the schema type definition
9200 * @ctxt: the schema parser context
9201 *
9202 * Fixup of the itemType reference of the list type.
9203 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009204static void
William M. Bracke7091952004-05-11 15:09:58 +00009205xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009206{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009207
Daniel Veillard01fa6152004-06-29 17:04:39 +00009208 if (((type->base == NULL) &&
9209 (type->subtypes == NULL)) ||
9210 ((type->base != NULL) &&
9211 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009212 /*
9213 * src-list-itemType-or-simpleType
9214 * Either the itemType [attribute] or the <simpleType> [child] of
9215 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009216 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009217 /*
9218 * TODO: Move this to the parse function.
9219 */
9220 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009221 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009222 NULL, type, type->node,
9223 "The attribute 'itemType' and the <simpleType> child "
9224 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009225 } else if (type->base!= NULL) {
9226 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9227 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009228 xmlSchemaPResCompAttrErr(ctxt,
9229 XML_SCHEMAP_SRC_RESOLVE,
9230 NULL, type, type->node,
9231 "itemType", type->base, type->baseNs,
9232 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009233 }
9234 }
9235 if ((type->subtypes != NULL) &&
9236 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9237 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009238}
9239
9240/**
9241 * xmlSchemaParseUnionRefCheck:
9242 * @typeDecl: the schema type definition
9243 * @ctxt: the schema parser context
9244 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009245 * Checks and builds the memberTypes of the union type.
9246 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009247 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009248static int
William M. Bracke7091952004-05-11 15:09:58 +00009249xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009250 xmlSchemaParserCtxtPtr ctxt)
9251{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009252
Daniel Veillard01fa6152004-06-29 17:04:39 +00009253 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9254 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009255
Daniel Veillard01fa6152004-06-29 17:04:39 +00009256 /* 1 If the <union> alternative is chosen, then [Definition:]
9257 * define the explicit members as the type definitions ·resolved·
9258 * to by the items in the ·actual value· of the memberTypes [attribute],
9259 * if any, followed by the type definitions corresponding to the
9260 * <simpleType>s among the [children] of <union>, if any.
9261 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009262
Daniel Veillard01fa6152004-06-29 17:04:39 +00009263 if (type->type != XML_SCHEMA_TYPE_UNION)
9264 return (-1);
9265 if (ctxt->ctxtType == NULL) {
9266 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009267 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009268 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9269 "available", NULL, NULL);
9270 return (-1);
9271 }
9272 /*
9273 * src-union-memberTypes-or-simpleTypes
9274 * Either the memberTypes [attribute] of the <union> element must
9275 * be non-empty or there must be at least one simpleType [child].
9276 */
9277 if ((type->base == NULL) &&
9278 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009279 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009280 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009281 NULL, NULL, type->node,
9282 "Either the attribute 'memberTypes' must be non-empty "
9283 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009284 }
9285
9286 ctxtType = ctxt->ctxtType;
9287 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009288 xmlAttrPtr attr;
9289 const xmlChar *cur, *end;
9290 xmlChar *tmp;
9291 const xmlChar *localName, *uri;
9292
9293 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009294 cur = type->base;
9295 do {
9296 while (IS_BLANK_CH(*cur))
9297 cur++;
9298 end = cur;
9299 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9300 end++;
9301 if (end == cur)
9302 break;
9303 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009304 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9305 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9306 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009307 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009308 xmlSchemaPResCompAttrErr(ctxt,
9309 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9310 NULL, NULL, type->node, "memberTypes", localName, uri,
9311 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009312 } else {
9313 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9314 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9315 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9316 if (link == NULL) {
9317 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9318 return (-1);
9319 }
9320 link->type = memberType;
9321 link->next = NULL;
9322 if (lastLink == NULL)
9323 ctxtType->memberTypes = link;
9324 else
9325 lastLink->next = link;
9326 lastLink = link;
9327 }
9328 xmlFree(tmp);
9329 cur = end;
9330 } while (*cur != 0);
9331 }
9332 /*
9333 * Add local simple types,
9334 */
9335 memberType = type->subtypes;
9336 while (memberType != NULL) {
9337 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9338 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9339 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9340 if (link == NULL) {
9341 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9342 return (-1);
9343 }
9344 link->type = memberType;
9345 link->next = NULL;
9346 if (lastLink == NULL)
9347 ctxtType->memberTypes = link;
9348 else
9349 lastLink->next = link;
9350 lastLink = link;
9351 memberType = memberType->next;
9352 }
9353 /*
9354 * The actual value is then formed by replacing any union type
9355 * definition in the ·explicit members· with the members of their
9356 * {member type definitions}, in order.
9357 */
9358 link = ctxtType->memberTypes;
9359 while (link != NULL) {
9360 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9361 subLink = link->type->memberTypes;
9362 if (subLink != NULL) {
9363 link->type = subLink->type;
9364 if (subLink->next != NULL) {
9365 lastLink = link->next;
9366 subLink = subLink->next;
9367 prevLink = link;
9368 while (subLink != NULL) {
9369 newLink = (xmlSchemaTypeLinkPtr)
9370 xmlMalloc(sizeof(xmlSchemaTypeLink));
9371 if (newLink == NULL) {
9372 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9373 NULL);
9374 return (-1);
9375 }
9376 newLink->type = memberType;
9377 prevLink->next = newLink;
9378 prevLink = newLink;
9379 newLink->next = lastLink;
9380
9381 subLink = subLink->next;
9382 }
9383 }
9384 }
9385 }
9386 link = link->next;
9387 }
9388
9389 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009390}
9391
Daniel Veillard4255d502002-04-16 15:50:10 +00009392/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009393 * xmlSchemaIsDerivedFromBuiltInType:
9394 * @ctxt: the schema parser context
9395 * @type: the type definition
9396 * @valType: the value type
9397 *
9398 *
9399 * Returns 1 if the type has the given value type, or
9400 * is derived from such a type.
9401 */
William M. Brack803812b2004-06-03 02:11:24 +00009402static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009403xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9404 xmlSchemaTypePtr type, int valType)
9405{
9406 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009407 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009408 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009409 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009410 return(1);
9411 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9412 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9413 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9414 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9415 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9416 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9417 if (type->baseType != NULL)
9418 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9419 valType));
9420 } else if ((type->subtypes != NULL) &&
9421 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9422 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9423 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9424 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9425 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9426 valType));
9427 }
9428
9429 return (0);
9430}
9431
9432/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009433 * xmlSchemaIsDerivedFromBuiltInType:
9434 * @type: the simpleType definition
9435 *
9436 * Returns the primitive type of the given type or
9437 * NULL in case of error.
9438 */
9439static xmlSchemaTypePtr
9440xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9441{
9442 while (type != NULL) {
9443 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9444 return (type);
9445 type = type->baseType;
9446 }
9447
9448 return (NULL);
9449}
9450
9451
9452/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009453 * xmlSchemaBuildAttributeUsesOwned:
9454 * @ctxt: the schema parser context
9455 * @type: the complex type definition
9456 * @cur: the attribute declaration list
9457 * @lastUse: the top of the attribute use list
9458 *
9459 * Builds the attribute uses list on the given complex type.
9460 * This one is supposed to be called by
9461 * xmlSchemaBuildAttributeValidation only.
9462 */
9463static int
9464xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9465 xmlSchemaAttributePtr cur,
9466 xmlSchemaAttributeLinkPtr *uses,
9467 xmlSchemaAttributeLinkPtr *lastUse)
9468{
9469 xmlSchemaAttributeLinkPtr tmp;
9470 while (cur != NULL) {
9471 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9472 /*
9473 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9474 * to by the ·actual value·s of the ref [attribute] of the
9475 * <attributeGroup> [children], if any."
9476 */
9477 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9478 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9479 lastUse) == -1) {
9480 return (-1);
9481 }
9482 } else {
9483 /* W3C: "1 The set of attribute uses corresponding to the
9484 * <attribute> [children], if any."
9485 */
9486 tmp = (xmlSchemaAttributeLinkPtr)
9487 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9488 if (tmp == NULL) {
9489 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9490 return (-1);
9491 }
9492 tmp->attr = cur;
9493 tmp->next = NULL;
9494 if (*uses == NULL)
9495 *uses = tmp;
9496 else
9497 (*lastUse)->next = tmp;
9498 *lastUse = tmp;
9499 }
9500 cur = cur->next;
9501 }
9502 return (0);
9503}
9504
Daniel Veillard50355f02004-06-08 17:52:16 +00009505/**
9506 * xmlSchemaCloneWildcardNsConstraints:
9507 * @ctxt: the schema parser context
9508 * @dest: the destination wildcard
9509 * @source: the source wildcard
9510 *
9511 * Clones the namespace constraints of source
9512 * and assignes them to dest.
9513 * Returns -1 on internal error, 0 otherwise.
9514 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009515static int
9516xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9517 xmlSchemaWildcardPtr *dest,
9518 xmlSchemaWildcardPtr source)
9519{
9520 xmlSchemaWildcardNsPtr cur, tmp, last;
9521
9522 if ((source == NULL) || (*dest == NULL))
9523 return(-1);
9524 (*dest)->any = source->any;
9525 cur = source->nsSet;
9526 last = NULL;
9527 while (cur != NULL) {
9528 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9529 if (tmp == NULL)
9530 return(-1);
9531 tmp->value = cur->value;
9532 if (last == NULL)
9533 (*dest)->nsSet = tmp;
9534 else
9535 last->next = tmp;
9536 last = tmp;
9537 cur = cur->next;
9538 }
9539 if ((*dest)->negNsSet != NULL)
9540 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9541 if (source->negNsSet != NULL) {
9542 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9543 if ((*dest)->negNsSet == NULL)
9544 return(-1);
9545 (*dest)->negNsSet->value = source->negNsSet->value;
9546 } else
9547 (*dest)->negNsSet = NULL;
9548 return(0);
9549}
9550
Daniel Veillard50355f02004-06-08 17:52:16 +00009551/**
9552 * xmlSchemaUnionWildcards:
9553 * @ctxt: the schema parser context
9554 * @completeWild: the first wildcard
9555 * @curWild: the second wildcard
9556 *
9557 * Unions the namespace constraints of the given wildcards.
9558 * @completeWild will hold the resulting union.
9559 * Returns a positive error code on failure, -1 in case of an
9560 * internal error, 0 otherwise.
9561 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009562static int
9563xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9564 xmlSchemaWildcardPtr completeWild,
9565 xmlSchemaWildcardPtr curWild)
9566{
9567 xmlSchemaWildcardNsPtr cur, curB, tmp;
9568
9569 /*
9570 * 1 If O1 and O2 are the same value, then that value must be the
9571 * value.
9572 */
9573 if ((completeWild->any == curWild->any) &&
9574 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9575 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9576
9577 if ((completeWild->negNsSet == NULL) ||
9578 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9579
9580 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009581 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009582
9583 /*
9584 * Check equality of sets.
9585 */
9586 cur = completeWild->nsSet;
9587 while (cur != NULL) {
9588 found = 0;
9589 curB = curWild->nsSet;
9590 while (curB != NULL) {
9591 if (cur->value == curB->value) {
9592 found = 1;
9593 break;
9594 }
9595 curB = curB->next;
9596 }
9597 if (!found)
9598 break;
9599 cur = cur->next;
9600 }
9601 if (found)
9602 return(0);
9603 } else
9604 return(0);
9605 }
9606 }
9607 /*
9608 * 2 If either O1 or O2 is any, then any must be the value
9609 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009610 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009611 if (completeWild->any == 0) {
9612 completeWild->any = 1;
9613 if (completeWild->nsSet != NULL) {
9614 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9615 completeWild->nsSet = NULL;
9616 }
9617 if (completeWild->negNsSet != NULL) {
9618 xmlFree(completeWild->negNsSet);
9619 completeWild->negNsSet = NULL;
9620 }
9621 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009622 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009623 }
9624 /*
9625 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9626 * then the union of those sets must be the value.
9627 */
9628 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9629 int found;
9630 xmlSchemaWildcardNsPtr start;
9631
9632 cur = curWild->nsSet;
9633 start = completeWild->nsSet;
9634 while (cur != NULL) {
9635 found = 0;
9636 curB = start;
9637 while (curB != NULL) {
9638 if (cur->value == curB->value) {
9639 found = 1;
9640 break;
9641 }
9642 curB = curB->next;
9643 }
9644 if (!found) {
9645 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9646 if (tmp == NULL)
9647 return (-1);
9648 tmp->value = cur->value;
9649 tmp->next = completeWild->nsSet;
9650 completeWild->nsSet = tmp;
9651 }
9652 cur = cur->next;
9653 }
9654
9655 return(0);
9656 }
9657 /*
9658 * 4 If the two are negations of different values (namespace names
9659 * or ·absent·), then a pair of not and ·absent· must be the value.
9660 */
9661 if ((completeWild->negNsSet != NULL) &&
9662 (curWild->negNsSet != NULL) &&
9663 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9664 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009665
9666 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009667 }
9668 /*
9669 * 5.
9670 */
9671 if (((completeWild->negNsSet != NULL) &&
9672 (completeWild->negNsSet->value != NULL) &&
9673 (curWild->nsSet != NULL)) ||
9674 ((curWild->negNsSet != NULL) &&
9675 (curWild->negNsSet->value != NULL) &&
9676 (completeWild->nsSet != NULL))) {
9677
9678 int nsFound, absentFound = 0;
9679
9680 if (completeWild->nsSet != NULL) {
9681 cur = completeWild->nsSet;
9682 curB = curWild->negNsSet;
9683 } else {
9684 cur = curWild->nsSet;
9685 curB = completeWild->negNsSet;
9686 }
9687 nsFound = 0;
9688 while (cur != NULL) {
9689 if (cur->value == NULL)
9690 absentFound = 1;
9691 else if (cur->value == curB->value)
9692 nsFound = 1;
9693 if (nsFound && absentFound)
9694 break;
9695 cur = cur->next;
9696 }
9697
9698 if (nsFound && absentFound) {
9699 /*
9700 * 5.1 If the set S includes both the negated namespace
9701 * name and ·absent·, then any must be the value.
9702 */
9703 completeWild->any = 1;
9704 if (completeWild->nsSet != NULL) {
9705 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9706 completeWild->nsSet = NULL;
9707 }
9708 if (completeWild->negNsSet != NULL) {
9709 xmlFree(completeWild->negNsSet);
9710 completeWild->negNsSet = NULL;
9711 }
9712 } else if (nsFound && (!absentFound)) {
9713 /*
9714 * 5.2 If the set S includes the negated namespace name
9715 * but not ·absent·, then a pair of not and ·absent· must
9716 * be the value.
9717 */
9718 if (completeWild->nsSet != NULL) {
9719 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9720 completeWild->nsSet = NULL;
9721 }
9722 if (completeWild->negNsSet == NULL) {
9723 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9724 if (completeWild->negNsSet == NULL)
9725 return (-1);
9726 }
9727 completeWild->negNsSet->value = NULL;
9728 } else if ((!nsFound) && absentFound) {
9729 /*
9730 * 5.3 If the set S includes ·absent· but not the negated
9731 * namespace name, then the union is not expressible.
9732 */
9733 xmlSchemaPErr(ctxt, completeWild->node,
9734 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009735 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009736 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009737 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009738 } else if ((!nsFound) && (!absentFound)) {
9739 /*
9740 * 5.4 If the set S does not include either the negated namespace
9741 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9742 * and a namespace name must be the value.
9743 */
9744 if (completeWild->negNsSet == NULL) {
9745 if (completeWild->nsSet != NULL) {
9746 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9747 completeWild->nsSet = NULL;
9748 }
9749 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9750 if (completeWild->negNsSet == NULL)
9751 return (-1);
9752 completeWild->negNsSet->value = curWild->negNsSet->value;
9753 }
9754 }
9755 return (0);
9756 }
9757 /*
9758 * 6.
9759 */
9760 if (((completeWild->negNsSet != NULL) &&
9761 (completeWild->negNsSet->value == NULL) &&
9762 (curWild->nsSet != NULL)) ||
9763 ((curWild->negNsSet != NULL) &&
9764 (curWild->negNsSet->value == NULL) &&
9765 (completeWild->nsSet != NULL))) {
9766
9767 if (completeWild->nsSet != NULL) {
9768 cur = completeWild->nsSet;
9769 } else {
9770 cur = curWild->nsSet;
9771 }
9772 while (cur != NULL) {
9773 if (cur->value == NULL) {
9774 /*
9775 * 6.1 If the set S includes ·absent·, then any must be the
9776 * value.
9777 */
9778 completeWild->any = 1;
9779 if (completeWild->nsSet != NULL) {
9780 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9781 completeWild->nsSet = NULL;
9782 }
9783 if (completeWild->negNsSet != NULL) {
9784 xmlFree(completeWild->negNsSet);
9785 completeWild->negNsSet = NULL;
9786 }
9787 return (0);
9788 }
9789 cur = cur->next;
9790 }
9791 if (completeWild->negNsSet == NULL) {
9792 /*
9793 * 6.2 If the set S does not include ·absent·, then a pair of not
9794 * and ·absent· must be the value.
9795 */
9796 if (completeWild->nsSet != NULL) {
9797 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9798 completeWild->nsSet = NULL;
9799 }
9800 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9801 if (completeWild->negNsSet == NULL)
9802 return (-1);
9803 completeWild->negNsSet->value = NULL;
9804 }
9805 return (0);
9806 }
9807 return (0);
9808
9809}
9810
Daniel Veillard50355f02004-06-08 17:52:16 +00009811/**
9812 * xmlSchemaIntersectWildcards:
9813 * @ctxt: the schema parser context
9814 * @completeWild: the first wildcard
9815 * @curWild: the second wildcard
9816 *
9817 * Intersects the namespace constraints of the given wildcards.
9818 * @completeWild will hold the resulting intersection.
9819 * Returns a positive error code on failure, -1 in case of an
9820 * internal error, 0 otherwise.
9821 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009822static int
9823xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9824 xmlSchemaWildcardPtr completeWild,
9825 xmlSchemaWildcardPtr curWild)
9826{
William M. Brack803812b2004-06-03 02:11:24 +00009827 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009828
9829 /*
9830 * 1 If O1 and O2 are the same value, then that value must be the
9831 * value.
9832 */
9833 if ((completeWild->any == curWild->any) &&
9834 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9835 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9836
9837 if ((completeWild->negNsSet == NULL) ||
9838 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9839
9840 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009841 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009842
9843 /*
9844 * Check equality of sets.
9845 */
9846 cur = completeWild->nsSet;
9847 while (cur != NULL) {
9848 found = 0;
9849 curB = curWild->nsSet;
9850 while (curB != NULL) {
9851 if (cur->value == curB->value) {
9852 found = 1;
9853 break;
9854 }
9855 curB = curB->next;
9856 }
9857 if (!found)
9858 break;
9859 cur = cur->next;
9860 }
9861 if (found)
9862 return(0);
9863 } else
9864 return(0);
9865 }
9866 }
9867 /*
9868 * 2 If either O1 or O2 is any, then the other must be the value.
9869 */
9870 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9871 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9872 return(-1);
9873 return(0);
9874 }
9875 /*
9876 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9877 * name or ·absent·) and the other is a set of (namespace names or
9878 * ·absent·), then that set, minus the negated value if it was in
9879 * the set, minus ·absent· if it was in the set, must be the value.
9880 */
9881 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9882 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9883 const xmlChar *neg;
9884
9885 if (completeWild->nsSet == NULL) {
9886 neg = completeWild->negNsSet->value;
9887 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9888 return(-1);
9889 } else
9890 neg = curWild->negNsSet->value;
9891 /*
9892 * Remove absent and negated.
9893 */
9894 prev = NULL;
9895 cur = completeWild->nsSet;
9896 while (cur != NULL) {
9897 if (cur->value == NULL) {
9898 if (prev == NULL)
9899 completeWild->nsSet = cur->next;
9900 else
9901 prev->next = cur->next;
9902 xmlFree(cur);
9903 break;
9904 }
9905 prev = cur;
9906 cur = cur->next;
9907 }
9908 if (neg != NULL) {
9909 prev = NULL;
9910 cur = completeWild->nsSet;
9911 while (cur != NULL) {
9912 if (cur->value == neg) {
9913 if (prev == NULL)
9914 completeWild->nsSet = cur->next;
9915 else
9916 prev->next = cur->next;
9917 xmlFree(cur);
9918 break;
9919 }
9920 prev = cur;
9921 cur = cur->next;
9922 }
9923 }
9924
9925 return(0);
9926 }
9927 /*
9928 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9929 * then the intersection of those sets must be the value.
9930 */
9931 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9932 int found;
9933
9934 cur = completeWild->nsSet;
9935 prev = NULL;
9936 while (cur != NULL) {
9937 found = 0;
9938 curB = curWild->nsSet;
9939 while (curB != NULL) {
9940 if (cur->value == curB->value) {
9941 found = 1;
9942 break;
9943 }
9944 curB = curB->next;
9945 }
9946 if (!found) {
9947 if (prev == NULL)
9948 completeWild->nsSet = cur->next;
9949 else
9950 prev->next = cur->next;
9951 tmp = cur->next;
9952 xmlFree(cur);
9953 cur = tmp;
9954 continue;
9955 }
9956 prev = cur;
9957 cur = cur->next;
9958 }
9959
9960 return(0);
9961 }
9962 /* 5 If the two are negations of different namespace names,
9963 * then the intersection is not expressible
9964 */
9965 if ((completeWild->negNsSet != NULL) &&
9966 (curWild->negNsSet != NULL) &&
9967 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9968 (completeWild->negNsSet->value != NULL) &&
9969 (curWild->negNsSet->value != NULL)) {
9970
9971 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009972 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009973 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009974 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009975 }
9976 /*
9977 * 6 If the one is a negation of a namespace name and the other
9978 * is a negation of ·absent·, then the one which is the negation
9979 * of a namespace name must be the value.
9980 */
9981 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9982 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9983 (completeWild->negNsSet->value == NULL)) {
9984 completeWild->negNsSet->value = curWild->negNsSet->value;
9985 }
9986 return(0);
9987}
9988
Daniel Veillard50355f02004-06-08 17:52:16 +00009989/**
9990 * xmlSchemaIsWildcardNsConstraintSubset:
9991 * @ctxt: the schema parser context
9992 * @wildA: the first wildcard
9993 * @wildB: the second wildcard
9994 *
9995 * Returns 1 if the namespace constraint of @wildA is an intensional
9996 * subset of @wildB, 0 otherwise.
9997 */
9998static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009999xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10000 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010001{
Daniel Veillard3646d642004-06-02 19:19:14 +000010002
Daniel Veillard50355f02004-06-08 17:52:16 +000010003 /*
10004 * Schema Component Constraint: Wildcard Subset
10005 */
10006 /*
10007 * 1 super must be any.
10008 */
10009 if (wildB->any)
10010 return (1);
10011 /*
10012 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10013 * 2.2 super must be a pair of not and the same value.
10014 */
10015 if ((wildA->negNsSet != NULL) &&
10016 (wildB->negNsSet != NULL) &&
10017 (wildA->negNsSet->value == wildA->negNsSet->value))
10018 return (1);
10019 /*
10020 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10021 */
10022 if (wildA->nsSet != NULL) {
10023 /*
10024 * 3.2.1 super must be the same set or a superset thereof.
10025 */
10026 if (wildB->nsSet != NULL) {
10027 xmlSchemaWildcardNsPtr cur, curB;
10028 int found = 0;
10029
10030 cur = wildA->nsSet;
10031 while (cur != NULL) {
10032 found = 0;
10033 curB = wildB->nsSet;
10034 while (curB != NULL) {
10035 if (cur->value == curB->value) {
10036 found = 1;
10037 break;
10038 }
10039 curB = curB->next;
10040 }
10041 if (!found)
10042 return (0);
10043 cur = cur->next;
10044 }
10045 if (found)
10046 return (1);
10047 } else if (wildB->negNsSet != NULL) {
10048 xmlSchemaWildcardNsPtr cur;
10049 /*
10050 * 3.2.2 super must be a pair of not and a namespace name or
10051 * ·absent· and that value must not be in sub's set.
10052 */
10053 cur = wildA->nsSet;
10054 while (cur != NULL) {
10055 if (cur->value == wildB->negNsSet->value)
10056 return (0);
10057 cur = cur->next;
10058 }
10059 return (1);
10060 }
10061 }
10062 return (0);
10063}
10064
10065/**
10066 * xmlSchemaBuildCompleteAttributeWildcard:
10067 * @ctxt: the schema parser context
10068 * @attrs: the attribute list
10069 * @completeWild: the resulting complete wildcard
10070 *
10071 * Returns -1 in case of an internal error, 0 otherwise.
10072 */
10073static int
10074xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10075 xmlSchemaAttributePtr attrs,
10076 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010077{
10078 while (attrs != NULL) {
10079 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10080 xmlSchemaAttributeGroupPtr group;
10081
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010082 group = (xmlSchemaAttributeGroupPtr) attrs;
10083 /*
10084 * Handle attribute group references.
10085 */
10086 if (group->ref != NULL) {
10087 if (group->refItem == NULL) {
10088 /*
10089 * TODO: Should we raise a warning here?
10090 */
10091 /*
10092 * The referenced attribute group definition could not
10093 * be resolved beforehand, so skip.
10094 */
10095 attrs = attrs->next;
10096 continue;
10097 } else
10098 group = group->refItem;
10099 }
10100 /*
10101 * For every attribute group definition, an intersected wildcard
10102 * will be created (assumed that a wildcard exists on the
10103 * particular attr. gr. def. or on any contained attr. gr. def
10104 * at all).
10105 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10106 * that the intersection will be performed only once.
10107 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010108 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10109 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010110 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10111 group->attributes, &group->attributeWildcard) == -1)
10112 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010113 }
10114 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10115 }
10116 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010117 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010118 /*
10119 * Copy the first encountered wildcard as context, except for the annotation.
10120 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010121 *completeWild = xmlSchemaAddWildcard(ctxt);
10122 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10123 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10124 completeWild, group->attributeWildcard) == -1)
10125 return (-1);
10126 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010127 /*
10128 * Although the complete wildcard might not correspond to any
10129 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010130 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010131 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010132 (*completeWild)->node = group->attributeWildcard->node;
10133
10134 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10135 xmlSchemaFreeWildcard(*completeWild);
10136 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010137 }
10138 }
10139 }
10140 attrs = attrs->next;
10141 }
10142
Daniel Veillard50355f02004-06-08 17:52:16 +000010143 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010144}
10145
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010146static int
10147xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10148 int *fixed,
10149 const xmlChar **value,
10150 xmlSchemaValPtr *val)
10151{
10152 *fixed = 0;
10153 *value = NULL;
10154 if (val != 0)
10155 *val = NULL;
10156
10157 if (item->defValue == NULL)
10158 item = item->refDecl;
10159
10160 if (item == NULL)
10161 return (0);
10162
10163 if (item->defValue != NULL) {
10164 *value = item->defValue;
10165 if (val != 0)
10166 *val = item->defVal;
10167 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10168 *fixed = 1;
10169 return (1);
10170 }
10171 return (0);
10172}
Daniel Veillard3646d642004-06-02 19:19:14 +000010173/**
10174 * xmlSchemaMatchesWildcardNs:
10175 * @wild: the wildcard
10176 * @ns: the namespace
10177 *
10178 *
10179 * Returns 1 if the given namespace matches the wildcard,
10180 * 0 otherwise.
10181 */
10182static int
10183xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10184{
10185 if (wild == NULL)
10186 return(0);
10187
10188 if (wild->any)
10189 return(1);
10190 else if (wild->nsSet != NULL) {
10191 xmlSchemaWildcardNsPtr cur;
10192
10193 cur = wild->nsSet;
10194 while (cur != NULL) {
10195 if (xmlStrEqual(cur->value, ns))
10196 return(1);
10197 cur = cur->next;
10198 }
10199 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10200 (!xmlStrEqual(wild->negNsSet->value, ns)))
10201 return(1);
10202
10203 return(0);
10204}
10205
10206/**
10207 * xmlSchemaBuildAttributeValidation:
10208 * @ctxt: the schema parser context
10209 * @type: the complex type definition
10210 *
10211 *
10212 * Builds the wildcard and the attribute uses on the given complex type.
10213 * Returns -1 if an internal error occurs, 0 otherwise.
10214 */
10215static int
10216xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10217{
10218 xmlSchemaTypePtr baseType = NULL;
10219 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010220 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010221 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010222 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010223 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010224 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010225 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010226
Daniel Veillard01fa6152004-06-29 17:04:39 +000010227 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010228 /*
10229 * Complex Type Definition with complex content Schema Component.
10230 *
10231 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010232 * TODO: Add checks for absent referenced attribute declarations and
10233 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010234 */
10235 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010236 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010237 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010238 "attribute uses already builded.\n",
10239 NULL, NULL);
10240 return (-1);
10241 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010242 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010243 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010244 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010245 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010246 type->name, NULL);
10247 return (-1);
10248 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010249 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010250 if (baseType == anyType)
10251 baseIsAnyType = 1;
10252 /*
10253 * Inherit the attribute uses of the base type.
10254 */
10255 /*
10256 * NOTE: It is allowed to "extend" the anyType complex type.
10257 */
10258 if (!baseIsAnyType) {
10259 if (baseType != NULL) {
10260 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10261 tmp = (xmlSchemaAttributeLinkPtr)
10262 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10263 if (tmp == NULL) {
10264 xmlSchemaPErrMemory(ctxt,
10265 "building attribute uses of complexType", NULL);
10266 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010267 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010268 tmp->attr = cur->attr;
10269 tmp->next = NULL;
10270 if (type->attributeUses == NULL) {
10271 type->attributeUses = tmp;
10272 } else
10273 lastBaseUse->next = tmp;
10274 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010275 }
10276 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010277 }
10278 if ((type->subtypes != NULL) &&
10279 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10280 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010281 /*
10282 * type --> (<simpleContent>|<complexContent>)
10283 * --> (<restriction>|<extension>) --> attributes
10284 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010285 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010286 } else {
10287 /* Short hand form of the complexType. */
10288 attrs = type->attributes;
10289 }
10290 /*
10291 * Handle attribute wildcards.
10292 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010293 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10294 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010295 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010296 * NOTE: During the parse time, the wildcard is created on the complexType
10297 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010298 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010299 if (err == -1) {
10300 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10301 "Internal error: xmlSchemaBuildAttributeValidation: "
10302 "failed to build an intersected attribute wildcard.\n",
10303 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010304 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010305 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010306
10307 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10308 ((baseIsAnyType) ||
10309 ((baseType != NULL) &&
10310 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10311 (baseType->attributeWildcard != NULL)))) {
10312 if (type->attributeWildcard != NULL) {
10313 /*
10314 * Union the complete wildcard with the base wildcard.
10315 */
10316 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10317 baseType->attributeWildcard) == -1)
10318 return (-1);
10319 } else {
10320 /*
10321 * Just inherit the wildcard.
10322 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010323 /*
10324 * NOTE: This is the only case where an attribute
10325 * wildcard is shared.
10326 */
10327 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10328 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010329 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010330 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010331 }
10332
10333 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10334 if (type->attributeWildcard != NULL) {
10335 /*
10336 * Derivation Valid (Restriction, Complex)
10337 * 4.1 The {base type definition} must also have one.
10338 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010339 if (baseType->attributeWildcard == NULL) {
10340 xmlSchemaPCustomErr(ctxt,
10341 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10342 NULL, type, NULL,
10343 "The type has an attribute wildcard, "
10344 "but the base type %s does not have one",
10345 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10346 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010347 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010348 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010349 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10350 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010351 xmlSchemaPCustomErr(ctxt,
10352 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10353 NULL, type, NULL,
10354 "The attribute wildcard is not a valid "
10355 "subset of the wildcard in the base type %s",
10356 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10357 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010358 return (1);
10359 }
10360 /* 4.3 Unless the {base type definition} is the ·ur-type
10361 * definition·, the complex type definition's {attribute
10362 * wildcard}'s {process contents} must be identical to or
10363 * stronger than the {base type definition}'s {attribute
10364 * wildcard}'s {process contents}, where strict is stronger
10365 * than lax is stronger than skip.
10366 */
10367 if ((type->baseType != anyType) &&
10368 (type->attributeWildcard->processContents <
10369 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010370 xmlSchemaPCustomErr(ctxt,
10371 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10372 NULL, type, NULL,
10373 "The 'process contents' of the attribute wildcard is weaker than "
10374 "the one in the base type %s",
10375 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10376 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010377 return (1);
10378 }
10379 }
10380 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10381 /*
10382 * Derivation Valid (Extension)
10383 * At this point the type and the base have both, either
10384 * no wildcard or a wildcard.
10385 */
10386 if ((baseType->attributeWildcard != NULL) &&
10387 (baseType->attributeWildcard != type->attributeWildcard)) {
10388 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010389 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010390 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010391 xmlSchemaPCustomErr(ctxt,
10392 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10393 NULL, type, NULL,
10394 "The attribute wildcard is not a valid "
10395 "superset of the one in the base type %s",
10396 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10397 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010398 return (1);
10399 }
10400 }
10401 }
10402
Daniel Veillard3646d642004-06-02 19:19:14 +000010403 /*
10404 * Gather attribute uses defined by this type.
10405 */
10406 if (attrs != NULL) {
10407 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10408 &uses, &lastUse) == -1) {
10409 return (-1);
10410 }
10411 }
10412 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10413 * "Two distinct attribute declarations in the {attribute uses} must
10414 * not have identical {name}s and {target namespace}s."
10415 *
10416 * For "extension" this is done further down.
10417 */
10418 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10419 cur = uses;
10420 while (cur != NULL) {
10421 tmp = cur->next;
10422 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010423 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10424 xmlSchemaGetAttrName(tmp->attr))) &&
10425 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10426 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10427
10428 xmlSchemaPAttrUseErr(ctxt,
10429 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10430 NULL, type, NULL, cur->attr,
10431 "Duplicate attribute use %s specified",
10432 xmlSchemaFormatNsUriLocal(&str,
10433 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10434 xmlSchemaGetAttrName(tmp->attr))
10435 );
10436 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010437 break;
10438 }
10439 tmp = tmp->next;
10440 }
10441 cur = cur->next;
10442 }
10443 }
10444 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10445 /*
10446 * Derive by restriction.
10447 */
10448 if (baseIsAnyType) {
10449 type->attributeUses = uses;
10450 } else {
10451 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010452 const xmlChar *bEffValue;
10453 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010454
10455 cur = uses;
10456 while (cur != NULL) {
10457 found = 0;
10458 base = type->attributeUses;
10459 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010460 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10461 xmlSchemaGetAttrName(base->attr)) &&
10462 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10463 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010464
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010465 found = 1;
10466
Daniel Veillard3646d642004-06-02 19:19:14 +000010467 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10468 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10469 /*
10470 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010471 */
10472 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010473 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010474 NULL, type, NULL, cur->attr,
10475 "The 'optional' use is inconsistent with a matching "
10476 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010477 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10478 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10479 /*
10480 * derivation-ok-restriction 3
10481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010482 xmlSchemaPCustomErr(ctxt,
10483 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10484 NULL, type, NULL,
10485 "A matching attribute use for the 'required' "
10486 "attribute use %s of the base type is missing",
10487 xmlSchemaFormatNsUriLocal(&str,
10488 xmlSchemaGetAttrTargetNsURI(base->attr),
10489 xmlSchemaGetAttrName(base->attr)));
10490 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010491 } else {
10492 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010493 * 2.1.3 [Definition:] Let the effective value
10494 * constraint of an attribute use be its {value
10495 * constraint}, if present, otherwise its {attribute
10496 * declaration}'s {value constraint} .
10497 */
10498 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10499 &bEffValue, 0);
10500 /*
10501 * 2.1.3 ... one of the following must be true
10502 *
10503 * 2.1.3.1 B's ·effective value constraint· is
10504 * ·absent· or default.
10505 */
10506 if ((bEffValue != NULL) &&
10507 (effFixed == 1)) {
10508 const xmlChar *rEffValue = NULL;
10509
10510 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10511 &rEffValue, 0);
10512 /*
10513 * 2.1.3.2 R's ·effective value constraint· is
10514 * fixed with the same string as B's.
10515 */
10516 if ((effFixed == 0) ||
10517 (! xmlStrEqual(rEffValue, bEffValue))) {
10518 xmlSchemaPAttrUseErr(ctxt,
10519 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10520 NULL, type, NULL, cur->attr,
10521 "The effective value constraint of the "
10522 "attribute use is inconsistent with "
10523 "its correspondent of the base type",
10524 NULL);
10525 }
10526 }
10527 /*
10528 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10529 */
10530 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010531 * Override the attribute use.
10532 */
10533 base->attr = cur->attr;
10534 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010535
Daniel Veillard3646d642004-06-02 19:19:14 +000010536 break;
10537 }
10538 base = base->next;
10539 }
10540
10541 if (!found) {
10542 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10543 /*
10544 * derivation-ok-restriction 2.2
10545 */
10546 if ((type->attributeWildcard != NULL) &&
10547 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10548 cur->attr->targetNamespace))
10549 found = 1;
10550
10551 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010552 xmlSchemaPAttrUseErr(ctxt,
10553 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10554 NULL, type, NULL, cur->attr,
10555 "Neither a matching attribute use, "
10556 "nor a matching wildcard in the base type does exist",
10557 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010558 } else {
10559 /*
10560 * Add the attribute use.
10561 *
10562 * Note that this may lead to funny derivation error reports, if
10563 * multiple equal attribute uses exist; but this is not
10564 * allowed anyway, and it will be reported beforehand.
10565 */
10566 tmp = cur;
10567 if (prev != NULL)
10568 prev->next = cur->next;
10569 else
10570 uses = cur->next;
10571 cur = cur->next;
10572 if (type->attributeUses == NULL) {
10573 type->attributeUses = tmp;
10574 } else
10575 lastBaseUse->next = tmp;
10576 lastBaseUse = tmp;
10577
10578 continue;
10579 }
10580 }
10581 }
10582 prev = cur;
10583 cur = cur->next;
10584 }
10585 if (uses != NULL)
10586 xmlSchemaFreeAttributeUseList(uses);
10587 }
10588 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10589 /*
10590 * The spec allows only appending, and not other kinds of extensions.
10591 *
10592 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10593 */
10594 if (uses != NULL) {
10595 if (type->attributeUses == NULL) {
10596 type->attributeUses = uses;
10597 } else
10598 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010599 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010600 } else {
10601 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010602 * Derive implicitely from the ur-type.
10603 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010604 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010605 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010606 /*
10607 * 3.4.6 -> Complex Type Definition Properties Correct
10608 */
10609 if (type->attributeUses != NULL) {
10610 cur = type->attributeUses;
10611 prev = NULL;
10612 while (cur != NULL) {
10613 /*
10614 * 4. Two distinct attribute declarations in the {attribute uses} must
10615 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010616 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010617 * Note that this was already done for "restriction" and types derived from
10618 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010619 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010620 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10621 tmp = cur->next;
10622 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010623 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10624 xmlSchemaGetAttrName(tmp->attr))) &&
10625 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10626 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010627
Daniel Veillardc0826a72004-08-10 14:17:33 +000010628 xmlSchemaPAttrUseErr(ctxt,
10629 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10630 NULL, type, NULL, tmp->attr,
10631 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010632 break;
10633 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010634 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010635 }
10636 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010637 /*
10638 * 5. Two distinct attribute declarations in the {attribute uses} must
10639 * not have {type definition}s which are or are derived from ID.
10640 */
10641 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010642 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010643 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010644 xmlSchemaPAttrUseErr(ctxt,
10645 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10646 NULL, type, NULL, cur->attr,
10647 "There must not exist more than one attribute use, "
10648 "declared of type 'ID' or derived from it",
10649 NULL);
10650 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010651 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010652 id = cur;
10653 }
10654 /*
10655 * Remove "prohibited" attribute uses. The reason this is done at this late
10656 * stage is to be able to catch dublicate attribute uses. So we had to keep
10657 * prohibited uses in the list as well.
10658 */
10659 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10660 tmp = cur;
10661 if (prev == NULL)
10662 type->attributeUses = cur->next;
10663 else
10664 prev->next = cur->next;
10665 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010666 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010667 } else {
10668 prev = cur;
10669 cur = cur->next;
10670 }
10671 }
10672 }
10673 /*
10674 * TODO: This check should be removed if we are 100% sure of
10675 * the base type attribute uses already being built.
10676 */
10677 if ((baseType != NULL) && (!baseIsAnyType) &&
10678 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10679 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010680 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010681 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010682 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010683 baseType->name, NULL);
10684 }
10685 return (0);
10686}
10687
10688/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010689 * xmlSchemaTypeFinalContains:
10690 * @schema: the schema
10691 * @type: the type definition
10692 * @final: the final
10693 *
10694 * Evaluates if a type definition contains the given "final".
10695 * This does take "finalDefault" into account as well.
10696 *
10697 * Returns 1 if the type does containt the given "final",
10698 * 0 otherwise.
10699 */
10700static int
10701xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10702{
10703 int tfinal = final, tflags = type->flags;
10704
10705 if (type == NULL)
10706 return (0);
10707 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10708 switch (final) {
10709 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10710 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10711 break;
10712 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10713 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10714 break;
10715 case XML_SCHEMAS_TYPE_FINAL_LIST:
10716 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10717 break;
10718 case XML_SCHEMAS_TYPE_FINAL_UNION:
10719 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10720 break;
10721 }
10722 tflags = schema->flags;
10723 }
10724 if (tflags & tfinal)
10725 return (1);
10726 else
10727 return (0);
10728
10729}
10730
10731/**
10732 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10733 * @type: the Union Simple Type
10734 *
10735 * Returns a list of member types of @type if existing,
10736 * returns NULL otherwise.
10737 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010738static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010739xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10740{
10741 while (type != NULL) {
10742 if (type->memberTypes != NULL)
10743 return (type->memberTypes);
10744 else
10745 type = type->baseType;
10746 }
10747 return (NULL);
10748}
10749
10750/**
10751 * xmlSchemaGetListSimpleTypeItemType:
10752 * @type: the simple type definition
10753 *
10754 * Returns the item type definition of the list simple type.
10755 */
10756static xmlSchemaTypePtr
10757xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10758{
10759 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10760 return (NULL);
10761 /*
10762 * Note: In libxml2, the built-in types do not reflect
10763 * the datatype hierarchy (yet?) - we have to treat them
10764 * in a special way.
10765 */
10766 if (type->type == XML_SCHEMA_TYPE_BASIC)
10767 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10768 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10769 /* 1 If the <list> alternative is chosen, then the type
10770 * definition ·resolved· to by the ·actual value· of the
10771 * itemType [attribute] of <list>, if present, otherwise
10772 * the type definition corresponding to the <simpleType>
10773 * among the [children] of <list>.
10774 */
10775 return (type->subtypes->subtypes);
10776 else {
10777 /* 2 If the <restriction> option is chosen, then the
10778 * {item type definition} of the {base type definition}.
10779 */
10780 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10781 }
10782}
10783
10784/**
10785 * xmlSchemaCheckCOSSTDerivedOK:
10786 * @type: the derived simple type definition
10787 * @baseType: the base type definition
10788 *
10789 * Checks wheter @type can be validly
10790 * derived from @baseType.
10791 *
10792 * Returns 0 on success, an positive error code otherwise.
10793 */
10794static int
10795xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10796 xmlSchemaTypePtr type,
10797 xmlSchemaTypePtr baseType,
10798 int subset)
10799{
10800 /*
10801 * Schema Component Constraint: Type Derivation OK (Simple)
10802 *
10803 *
10804 * 1 They are the same type definition.
10805 * TODO: The identy check might have to be more complex than this.
10806 */
10807 if (type == baseType)
10808 return (0);
10809 /*
10810 * 2.1 restriction is not in the subset, or in the {final}
10811 * of its own {base type definition};
10812 */
10813 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10814 (xmlSchemaTypeFinalContains(schema,
10815 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10816 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10817 }
10818 /* 2.2 */
10819 if (type->baseType == baseType) {
10820 /*
10821 * 2.2.1 D's ·base type definition· is B.
10822 */
10823 return (0);
10824 }
10825 /*
10826 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10827 * and is validly derived from B given the subset, as defined by this
10828 * constraint.
10829 */
10830 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10831 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10832 return (0);
10833 }
10834 /*
10835 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10836 * definition·.
10837 */
10838 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10839 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10840 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10841 return (0);
10842 }
10843 /*
10844 * 2.2.4 B's {variety} is union and D is validly derived from a type
10845 * definition in B's {member type definitions} given the subset, as
10846 * defined by this constraint.
10847 *
10848 * NOTE: This seems not to involve built-in types, since there is no
10849 * built-in Union Simple Type.
10850 */
10851 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10852 xmlSchemaTypeLinkPtr cur;
10853
10854 cur = baseType->memberTypes;
10855 while (cur != NULL) {
10856 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10857 cur->type, subset) == 0)
10858 return (0);
10859 cur = cur->next;
10860 }
10861 }
10862
10863 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10864}
10865
10866
10867/**
10868 * xmlSchemaCheckSTPropsCorrect:
10869 * @ctxt: the schema parser context
10870 * @type: the simple type definition
10871 *
10872 * Checks st-props-correct.
10873 *
10874 * Returns 0 if the properties are correct,
10875 * if not, a positive error code and -1 on internal
10876 * errors.
10877 */
10878static int
10879xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10880 xmlSchemaTypePtr type)
10881{
10882 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10883 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010884 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010885
Daniel Veillardc0826a72004-08-10 14:17:33 +000010886 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010887 /*
10888 * Schema Component Constraint: Simple Type Definition Properties Correct
10889 *
10890 * NOTE: This is somehow redundant, since we actually built a simple type
10891 * to have all the needed information; this acts as an self test.
10892 */
10893 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10894 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10895 /*
10896 * TODO: 1 The values of the properties of a simple type definition must be as
10897 * described in the property tableau in Datatype definition, modulo the
10898 * impact of Missing Sub-components (§5.3).
10899 */
10900 /* Base type: If the datatype has been ·derived· by ·restriction·
10901 * then the Simple Type Definition component from which it is ·derived·,
10902 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10903 */
10904 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010905 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010906 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010907 NULL, type, NULL,
10908 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010909 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10910 }
10911 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10912 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10913 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010914 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010915 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010916 NULL, type, NULL,
10917 "The base type %s is not a simple type",
10918 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10919 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010920 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10921 }
10922 if ((baseType != anySimpleType) &&
10923 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010924 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010925 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010926 NULL, type, NULL,
10927 "A type, derived by list or union, must have"
10928 "the simple ur-type definition as base type, not %s",
10929 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10930 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010931 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10932 }
10933 /*
10934 * Variety: One of {atomic, list, union}.
10935 */
10936 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10937 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10938 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010939 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010940 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010941 NULL, type, NULL,
10942 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010943 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10944 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010945 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010946
10947 /*
10948 * 2 All simple type definitions must be derived ultimately from the ·simple
10949 * ur-type definition (so· circular definitions are disallowed). That is, it
10950 * must be possible to reach a built-in primitive datatype or the ·simple
10951 * ur-type definition· by repeatedly following the {base type definition}.
10952 */
10953 baseType = type->baseType;
10954 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10955 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10956 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10957 if (baseType == anySimpleType)
10958 break;
10959 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010960 xmlSchemaPCustomErr(ctxt,
10961 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10962 NULL, type, NULL,
10963 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010964 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10965 }
10966 baseType = baseType->baseType;
10967 }
10968 /*
10969 * 3 The {final} of the {base type definition} must not contain restriction.
10970 */
10971 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10972 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010973 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010974 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010975 NULL, type, NULL,
10976 "The 'final' of its base type %s must not contain "
10977 "'restriction'",
10978 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10979 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010980 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10981 }
10982 return (0);
10983}
10984
10985/**
10986 * xmlSchemaCheckDerivationValidSimpleRestriction:
10987 * @ctxt: the schema parser context
10988 * @type: the simple type definition
10989 *
10990 * Checks if the given @type (simpleType) is derived
10991 * validly by restriction.
10992 *
10993 * Returns -1 on internal errors, 0 if the type is validly derived,
10994 * a positive error code otherwise.
10995 */
10996static int
10997xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010998 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010999{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011000 xmlChar *str = NULL;
11001
11002 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011003
11004 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11005 xmlSchemaPErr(ctxt, type->node,
11006 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011007 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11008 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011009 type->name, NULL);
11010 return (-1);
11011 }
11012
11013 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11014 xmlSchemaTypePtr primitive;
11015 /*
11016 * 1.1 The {base type definition} must be an atomic simple
11017 * type definition or a built-in primitive datatype.
11018 */
11019 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011020 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011021 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011022 NULL, type, NULL,
11023 "The base type %s is not an atomic simple type",
11024 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11025 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011026 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11027 }
11028 /* 1.2 The {final} of the {base type definition} must not contain
11029 * restriction.
11030 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011031 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011032 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11033 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011034 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011035 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011036 NULL, type, NULL,
11037 "The final of its base type %s must not contain 'restriction'",
11038 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11039 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011040 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11041 }
11042
11043 /*
11044 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11045 * type definition}, as specified in the appropriate subsection of 3.2
11046 * Primitive datatypes.
11047 */
11048 if (type->facets != NULL) {
11049 xmlSchemaFacetPtr facet;
11050 int ok = 1;
11051
11052 primitive = xmlSchemaGetPrimitiveType(type);
11053 if (primitive == NULL) {
11054 xmlSchemaPErr(ctxt, type->node,
11055 XML_ERR_INTERNAL_ERROR,
11056 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011057 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011058 type->name, NULL);
11059 return (-1);
11060 }
11061 facet = type->facets;
11062 do {
11063 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011064 ok = 0;
11065 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011066 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011067 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011068 }
11069 facet = facet->next;
11070 } while (facet != NULL);
11071 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011072 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011073 }
11074 /*
11075 * TODO: 1.3.2 (facet derivation)
11076 */
11077 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11078 xmlSchemaTypePtr itemType = NULL;
11079
11080 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11081 if (itemType == NULL) {
11082 xmlSchemaPErr(ctxt, type->node,
11083 XML_ERR_INTERNAL_ERROR,
11084 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011085 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011086 type->name, NULL);
11087 return (-1);
11088 }
11089 /*
11090 * 2.1 The {item type definition} must have a {variety} of atomic or
11091 * union (in which case all the {member type definitions}
11092 * must be atomic).
11093 */
11094 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11095 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011097 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011098 NULL, type, NULL,
11099 "The item type %s must have a variety of atomic or union",
11100 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11101 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011102 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11103 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11104 xmlSchemaTypeLinkPtr member;
11105
11106 member = itemType->memberTypes;
11107 while (member != NULL) {
11108 if ((member->type->flags &
11109 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011110 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011111 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011112 NULL, type, NULL,
11113 "The item type is a union type, but the "
11114 "member type %s of this item type is not atomic",
11115 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11116 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011117 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11118 }
11119 member = member->next;
11120 }
11121 }
11122
11123 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11124 xmlSchemaFacetPtr facet;
11125 /*
11126 * This is the case if we have: <simpleType><list ..
11127 */
11128 /*
11129 * 2.3.1
11130 * 2.3.1.1 The {final} of the {item type definition} must not
11131 * contain list.
11132 */
11133 if (xmlSchemaTypeFinalContains(ctxt->schema,
11134 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011135 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011136 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011137 NULL, type, NULL,
11138 "The final of its item type %s must not contain 'list'",
11139 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11140 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011141 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11142 }
11143 /*
11144 * 2.3.1.2 The {facets} must only contain the whiteSpace
11145 * facet component.
11146 */
11147 if (type->facets != NULL) {
11148 facet = type->facets;
11149 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011150 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11151 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011152 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011153 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011154 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11155 }
11156 facet = facet->next;
11157 } while (facet != NULL);
11158 }
11159 /*
11160 * TODO: Datatypes states:
11161 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11162 * whose ·lexical space· allows space (such as string or anyURI)or
11163 * a ·union· datatype any of whose {member type definitions}'s
11164 * ·lexical space· allows space.
11165 */
11166 } else {
11167 /*
11168 * This is the case if we have: <simpleType><restriction ...
11169 */
11170 /*
11171 * 2.3.2
11172 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11173 */
11174 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011175 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011176 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011177 NULL, type, NULL,
11178 "The base type %s must be a list type",
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_2_3_2_1);
11182 }
11183 /*
11184 * 2.3.2.2 The {final} of the {base type definition} must not
11185 * contain restriction.
11186 */
11187 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11188 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011189 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011190 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011191 NULL, type, NULL,
11192 "The final of the base type %s must not contain 'restriction'",
11193 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11194 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011195 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11196 }
11197 /*
11198 * 2.3.2.3 The {item type definition} must be validly derived
11199 * from the {base type definition}'s {item type definition} given
11200 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11201 */
11202 {
11203 xmlSchemaTypePtr baseItemType;
11204
11205 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11206 if (baseItemType == NULL) {
11207 xmlSchemaPErr(ctxt, type->node,
11208 XML_ERR_INTERNAL_ERROR,
11209 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011210 "List simple type '%s': Failed to "
11211 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011212 type->name, type->baseType->name);
11213 return (-1);
11214 }
11215 if ((itemType != baseItemType) &&
11216 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11217 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011218 xmlChar *strBIT = NULL, *strBT = NULL;
11219 xmlSchemaPCustomErrExt(ctxt,
11220 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11221 NULL, type, NULL,
11222 "The item type %s is not validly derived from the "
11223 "item type %s of the base type %s",
11224 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11225 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11226 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11227
11228 FREE_AND_NULL(str)
11229 FREE_AND_NULL(strBIT)
11230 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011231 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11232 }
11233 }
11234
11235 if (type->facets != NULL) {
11236 xmlSchemaFacetPtr facet;
11237 int ok = 1;
11238 /*
11239 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11240 * and enumeration facet components are allowed among the {facets}.
11241 */
11242 facet = type->facets;
11243 do {
11244 switch (facet->type) {
11245 case XML_SCHEMA_FACET_LENGTH:
11246 case XML_SCHEMA_FACET_MINLENGTH:
11247 case XML_SCHEMA_FACET_MAXLENGTH:
11248 case XML_SCHEMA_FACET_WHITESPACE:
11249 /*
11250 * TODO: 2.5.1.2 List datatypes
11251 * The value of ·whiteSpace· is fixed to the value collapse.
11252 */
11253 case XML_SCHEMA_FACET_PATTERN:
11254 case XML_SCHEMA_FACET_ENUMERATION:
11255 break;
11256 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011257 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011258 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011259 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011260 /*
11261 * We could return, but it's nicer to report all
11262 * invalid facets.
11263 */
11264 ok = 0;
11265 }
11266 }
11267 facet = facet->next;
11268 } while (facet != NULL);
11269 if (ok == 0)
11270 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11271 /*
11272 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11273 * is a facet of the same kind in the {facets} of the {base type
11274 * definition} (call this BF),then the DF's {value} must be a valid
11275 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11276 */
11277 }
11278
11279
11280 }
11281 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11282 /*
11283 * 3.1 The {member type definitions} must all have {variety} of
11284 * atomic or list.
11285 */
11286 xmlSchemaTypeLinkPtr member;
11287
11288 member = type->memberTypes;
11289 while (member != NULL) {
11290 if (((member->type->flags &
11291 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11292 ((member->type->flags &
11293 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011294 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011295 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011296 NULL, type, NULL,
11297 "The member type %s is neither an atomic, nor a list type",
11298 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11299 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011300 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11301 }
11302 member = member->next;
11303 }
11304 /*
11305 * 3.3.1 If the {base type definition} is the ·simple ur-type
11306 * definition·
11307 */
11308 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11309 /*
11310 * 3.3.1.1 All of the {member type definitions} must have a
11311 * {final} which does not contain union.
11312 */
11313 member = type->memberTypes;
11314 while (member != NULL) {
11315 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11316 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011317 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011318 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011319 NULL, type, NULL,
11320 "The final of member type %s contains 'union'",
11321 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11322 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011323 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11324 }
11325 member = member->next;
11326 }
11327 /*
11328 * 3.3.1.2 The {facets} must be empty.
11329 */
11330 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011331 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011332 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011333 NULL, type, NULL,
11334 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011335 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11336 }
11337 } else {
11338 /*
11339 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11340 */
11341 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011342 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011343 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011344 NULL, type, NULL,
11345 "The base type %s is not a union type",
11346 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11347 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011348 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11349 }
11350 /*
11351 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11352 */
11353 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11354 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011355 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011356 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011357 NULL, type, NULL,
11358 "The final of its base type %s must not contain 'restriction'",
11359 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11360 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011361 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11362 }
11363 /*
11364 * 3.3.2.3 The {member type definitions}, in order, must be validly
11365 * derived from the corresponding type definitions in the {base
11366 * type definition}'s {member type definitions} given the empty set,
11367 * as defined in Type Derivation OK (Simple) (§3.14.6).
11368 */
11369 {
11370 xmlSchemaTypeLinkPtr baseMember;
11371
11372 /*
11373 * OPTIMIZE: if the type is restricting, it has no local defined
11374 * member types and inherits the member types of the base type;
11375 * thus a check for equality can be skipped.
11376 */
11377 /*
11378 * TODO: Even worse: I cannot see a scenario where a restricting
11379 * union simple type can have other member types as the member
11380 * types of it's base type. This check seems not necessary with
11381 * respect to the derivation process in libxml2.
11382 */
11383 if (type->memberTypes != NULL) {
11384 member = type->memberTypes;
11385 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11386 if ((member == NULL) && (baseMember != NULL)) {
11387 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011388 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011389 "Internal error: "
11390 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011391 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011392 "of member types in the base type\n",
11393 type->name, NULL);
11394 }
11395 while (member != NULL) {
11396 if (baseMember == NULL) {
11397 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011398 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011399 "Internal error: "
11400 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011401 "(3.3.2.3), union simple type '%s', unequal number "
11402 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011403 type->name, NULL);
11404 }
11405 if ((member->type != baseMember->type) &&
11406 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11407 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011408 xmlChar *strBMT = NULL, *strBT = NULL;
11409
11410 xmlSchemaPCustomErrExt(ctxt,
11411 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11412 NULL, type, NULL,
11413 "The member type %s is not validly derived from its "
11414 "corresponding member type %s of the base type %s",
11415 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11416 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11417 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11418 FREE_AND_NULL(str)
11419 FREE_AND_NULL(strBMT)
11420 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011421 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11422 }
11423 member = member->next;
11424 baseMember = baseMember->next;
11425 }
11426 }
11427 }
11428 /*
11429 * 3.3.2.4 Only pattern and enumeration facet components are
11430 * allowed among the {facets}.
11431 */
11432 if (type->facets != NULL) {
11433 xmlSchemaFacetPtr facet;
11434 int ok = 1;
11435
11436 facet = type->facets;
11437 do {
11438 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11439 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011440 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11441 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11442 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011443 ok = 0;
11444 }
11445 facet = facet->next;
11446 } while (facet != NULL);
11447 if (ok == 0)
11448 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11449
11450 }
11451 /*
11452 * TODO: 3.3.2.5 (facet derivation)
11453 */
11454 }
11455 }
11456
11457 return (0);
11458}
11459
11460/**
11461 * xmlSchemaCheckSRCSimpleType:
11462 * @ctxt: the schema parser context
11463 * @type: the simple type definition
11464 *
11465 * Checks crc-simple-type constraints.
11466 *
11467 * Returns 0 if the constraints are satisfied,
11468 * if not a positive error code and -1 on internal
11469 * errors.
11470 */
11471static int
11472xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11473 xmlSchemaTypePtr type)
11474{
11475 /*
11476 * NOTE: src-simple-type 2-4 are redundant, since the checks
11477 * were are done for the corresponding <restriction>, <list> and <union>
11478 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11479 * Maby this can be skipped in the future, if we get sure it's not needed.
11480 */
11481 if (type->subtypes == NULL) {
11482 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011483 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011484 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011485 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011486 type->name, NULL);
11487 return (-1);
11488 }
11489 /*
11490 * src-simple-type.1 The corresponding simple type definition, if any,
11491 * must satisfy the conditions set out in Constraints on Simple Type
11492 * Definition Schema Components (§3.14.6).
11493 */
11494 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11495 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11496 /*
11497 * TODO: Removed this, since it got annoying to get an
11498 * extra error report, if anything failed until now.
11499 * Enable this if needed.
11500 */
11501 /*
11502 xmlSchemaPErr(ctxt, type->node,
11503 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011504 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011505 "on simple type definitions.\n",
11506 type->name, NULL);
11507 */
11508 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11509 }
11510
11511 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11512 /*
11513 * src-simple-type.2 If the <restriction> alternative is chosen,
11514 * either it must have a base [attribute] or a <simpleType> among its
11515 * [children], but not both.
11516 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011517 /*
11518 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11519 * NOTE: This was removed, since this will be already handled
11520 * in the parse function for <restriction>.
11521 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011522 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11523 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11524 * an itemType [attribute] or a <simpleType> among its [children],
11525 * but not both.
11526 * NOTE: baseType is set to the local simple type definiton,
11527 * if existent, at parse time. This is a hack and not nice.
11528 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011529 /*
11530 * TODO: Remove this, and add the check to the parse function of <list>.
11531 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011532 if (((type->subtypes->base == NULL) &&
11533 (type->baseType == NULL)) ||
11534 ((type->subtypes->base != NULL) &&
11535 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011536 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011537 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011538 NULL, type, NULL,
11539 "Either the attribute 'itemType' or the <simpleType> child "
11540 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011541 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11542 }
11543
11544
11545 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11546 xmlSchemaTypeLinkPtr member;
11547 xmlSchemaTypePtr ancestor, anySimpleType;
11548
11549 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11550
11551 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11552 * the <union> alternative is chosen, there must not be any entries
11553 * in the memberTypes [attribute] at any depth which resolve to the
11554 * component corresponding to the <simpleType>.
11555 */
11556 member = type->memberTypes;
11557 while (member != NULL) {
11558 ancestor = member->type;
11559 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11560 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11561 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11562 if (ancestor == anySimpleType)
11563 break;
11564 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011565 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011566 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011567 NULL, type, NULL,
11568 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011569 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11570 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11571 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011572 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011573 * type as item type, which in turn has a list ST as member
11574 * type, we will assume this here as well, since this check
11575 * was not yet performed.
11576 */
11577
11578 }
11579 ancestor = ancestor->baseType;
11580 }
11581 member = member->next;
11582 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011583 }
11584
11585 return (0);
11586}
11587
William M. Brack2f2a6632004-08-20 23:09:47 +000011588#if 0 /* Not yet used code for CT schema validation */
11589static int
11590xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11591 const xmlChar * value,
11592 xmlSchemaTypePtr type,
11593 int fireErrors)
11594{
11595 int ret;
11596 /*
11597 * 3.14.4 Simple Type Definition Validation Rules
11598 * Validation Rule: String Valid
11599 */
11600 /*
11601 * 1 It is schema-valid with respect to that definition as defined
11602 * by Datatype Valid in [XML Schemas: Datatypes].
11603 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011604 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11605 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011606 return (ret);
11607 /*
11608 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11609 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11610 * the string must be a ·declared entity name·.
11611 */
11612 /*
11613 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11614 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11615 * then every whitespace-delimited substring of the string must be a ·declared
11616 * entity name·.
11617 */
11618 /*
11619 * 2.3 otherwise no further condition applies.
11620 */
11621
11622 return (0);
11623}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011624#endif
11625
William M. Brack2f2a6632004-08-20 23:09:47 +000011626
11627static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011628xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11629{
11630 if (vctxt->pctxt == NULL) {
11631 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11632 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11633 if (vctxt->pctxt == NULL) {
11634 xmlSchemaVErr(vctxt, NULL,
11635 XML_SCHEMAV_INTERNAL,
11636 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11637 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011638 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011639 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011640 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011641 /* TODO: Pass user data. */
11642 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11643 }
11644 return (0);
11645}
11646
11647static int
11648xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11649{
11650 if (ctxt->vctxt == NULL) {
11651 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11652 if (ctxt->vctxt == NULL) {
11653 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011654 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011655 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11656 "failed to create a temp. validation context.\n",
11657 NULL, NULL);
11658 return (-1);
11659 }
11660 /* TODO: Pass user data. */
11661 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11662 }
11663 return (0);
11664}
11665
11666/**
11667 * xmlSchemaCheckCOSValidDefault:
11668 * @ctxt: the schema parser context
11669 * @type: the simple type definition
11670 * @value: the default value
11671 * @node: an optional node (the holder of the value)
11672 *
11673 * Checks the "cos-valid-default" constraints.
11674 *
11675 * Returns 0 if the constraints are satisfied,
11676 * if not, a positive error code and -1 on internal
11677 * errors.
11678 */
11679static int
11680xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11681 xmlSchemaValidCtxtPtr vctxt,
11682 xmlSchemaTypePtr type,
11683 const xmlChar *value,
11684 xmlNodePtr node)
11685{
11686 int ret = 0;
11687
11688 /*
11689 * cos-valid-default:
11690 * Schema Component Constraint: Element Default Valid (Immediate)
11691 * For a string to be a valid default with respect to a type
11692 * definition the appropriate case among the following must be true:
11693 */
11694 /*
11695 * NOTE: This has to work without a given node (the holder of the
11696 * value), since it should work on the component, i.e. an underlying
11697 * DOM must not be mandatory.
11698 */
11699 if ((pctxt == NULL) || (vctxt == NULL)) {
11700 xmlSchemaPErr(pctxt, node,
11701 XML_SCHEMAP_INTERNAL,
11702 "Internal error: xmlSchemaCheckCOSValidDefault, "
11703 "bad arguments: the parser and/or validation context is "
11704 "missing.\n",
11705 NULL, NULL);
11706 return (-1);
11707 }
11708 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011709 /*
11710 * Complex type.
11711 *
11712 * 2.1 its {content type} must be a simple type definition or mixed.
11713 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011714 /*
11715 * TODO: Adjust this when the content type will be computed
11716 * correctly.
11717 */
11718 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11719 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11720 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11721 xmlSchemaPSimpleTypeErr(pctxt,
11722 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11723 NULL, NULL, node,
11724 type, NULL, NULL,
11725 "If the type of a constraint value is complex, its content "
11726 "type must be mixed or a simple type",
11727 NULL, NULL);
11728 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11729 }
11730 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011731 /*
11732 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11733 * particle must be ·emptiable· as defined by Particle Emptiable
11734 * (§3.9.6).
11735 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011736
William M. Brack2f2a6632004-08-20 23:09:47 +000011737 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011738 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011739 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011740 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011741 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011742 }
11743 /*
11744 * 1 If the type definition is a simple type definition, then the string
11745 * must be ·valid· with respect to that definition as defined by String
11746 * Valid (§3.14.4).
11747 *
11748 * AND
11749 *
11750 * 2.2.1 If the {content type} is a simple type definition, then the
11751 * string must be ·valid· with respect to that simple type definition
11752 * as defined by String Valid (§3.14.4).
11753 */
11754 vctxt->node = node;
11755 vctxt->cur = NULL;
11756 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11757 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11758 if (ret < 0) {
11759 xmlSchemaPErr(pctxt, node,
11760 /* NOTNICE: error code: This function will be used during
11761 * schema construction and xsi:type validation.
11762 */
11763 XML_SCHEMAP_INTERNAL,
11764 "Internal error: xmlSchemaCheckCOSValidDefault, "
11765 "while validating a value constaint value.\n",
11766 NULL, NULL);
11767
11768 }
11769 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011770}
11771
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011772#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011773/**
11774 * xmlSchemaGetSTContentOfCT:
11775 * @ctxt: the schema parser context
11776 * @type: the complex type definition
11777 *
11778 *
11779 * Returns the corresponding simple type for the content of
11780 * the complex type.
11781 */
11782static xmlSchemaTypePtr
11783xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11784 xmlSchemaTypePtr type)
11785{
11786 xmlSchemaTypePtr orig = type, anyType;
11787
11788 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11789 while ((type != NULL) && (type != anyType) &&
11790 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11791 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11792 return(type);
11793 type = type->baseType;
11794 }
11795 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011796 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011797 NULL, orig, NULL,
11798 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11799 "no simple type for the content of complex type '%s' could be "
11800 "computed", orig->name);
11801 return (NULL);
11802}
11803
11804
William M. Brack2f2a6632004-08-20 23:09:47 +000011805
William M. Brack2f2a6632004-08-20 23:09:47 +000011806
11807/**
11808 * xmlSchemaCheckCOSCTExtends:
11809 * @ctxt: the schema parser context
11810 * @type: the complex type definition
11811 *
11812 * Schema Component Constraint: Derivation Valid (Extension)
11813 *
11814 * Returns 0 if the constraints are satisfied, a positive
11815 * error code if not and -1 if an internal error occured.
11816 */
11817static int
11818xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11819 xmlSchemaTypePtr type)
11820{
11821 xmlSchemaTypePtr base;
11822 /*
11823 * 1 If the {base type definition} is a complex type definition,
11824 * then all of the following must be true:
11825 */
11826 base = type->baseType;
11827 if (base == NULL) {
11828 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011829 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011830 NULL, type, NULL,
11831 "Internal error: xmlSchemaCheckCOSCTExtends, "
11832 "the complex type '%s' has no base type", type->name);
11833 return (-1);
11834 }
11835 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11836 /*
11837 * 1.1 The {final} of the {base type definition} must not
11838 * contain extension.
11839 */
11840 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11841 xmlSchemaPCustomErr(ctxt,
11842 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11843 NULL, type, NULL,
11844 "The 'final' of the base type definition "
11845 "contains extension", NULL);
11846 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11847 }
11848 /*
11849 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11850 * of the complex type definition itself, that is, for every attribute
11851 * use in the {attribute uses} of the {base type definition}, there
11852 * must be an attribute use in the {attribute uses} of the complex
11853 * type definition itself whose {attribute declaration} has the same
11854 * {name}, {target namespace} and {type definition} as its attribute
11855 * declaration
11856 *
11857 * NOTE: This will be already satisfied by the way the attribute uses
11858 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11859 * is not needed.
11860 */
11861
11862 /*
11863 * 1.3 If it has an {attribute wildcard}, the complex type definition
11864 * must also have one, and the base type definition's {attribute
11865 * wildcard}'s {namespace constraint} must be a subset of the complex
11866 * type definition's {attribute wildcard}'s {namespace constraint},
11867 * as defined by Wildcard Subset (§3.10.6).
11868 *
11869 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11870 * this check is not needed.
11871 */
11872
11873 /*
11874 * 1.4 One of the following must be true:
11875 *
11876 * 1.4.1 The {content type} of the {base type definition} and the
11877 * {content type} of the complex type definition itself must be the same
11878 * simple type definition
11879 */
11880
11881
11882
11883 } else {
11884 /*
11885 * 2 If the {base type definition} is a simple type definition,
11886 * then all of the following must be true:
11887 */
11888 /*
11889 * 2.1 The {content type} must be the same simple type definition.
11890 */
11891 /*
11892 * 2.2 The {final} of the {base type definition} must not contain
11893 * extension
11894 */
11895 }
11896
11897}
11898
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011899static int
11900xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11901 xmlSchemaTypePtr type)
11902{
11903 xmlSchemaTypePtr base, content;
11904 int OK = 0;
11905
11906 /*
11907 * TODO: Adjust the error codes here, as I used
11908 * XML_SCHEMAP_SRC_CT_1 only yet.
11909 */
11910 /*
11911 * Schema Representation Constraint:
11912 * Complex Type Definition Representation OK
11913 */
11914 base = type->baseType;
11915 if (base == NULL) {
11916 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11917 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11918 type->name);
11919 return (-1);
11920 }
11921
11922 if (type->subtypes != NULL) {
11923 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11924 if IS_COMPLEX_TYPE(base) {
11925 /*
11926 * 1 If the <complexContent> alternative is chosen, the type definition
11927 * ·resolved· to by the ·actual value· of the base [attribute]
11928 * must be a complex type definition;
11929 */
11930 xmlSchemaPCustomErr(ctxt,
11931 XML_SCHEMAP_SRC_CT_1,
11932 NULL, type, NULL,
11933 "The base type is not a complex type", NULL);
11934 return (XML_SCHEMAP_SRC_CT_1);
11935 }
11936 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11937
11938 if IS_SIMPLE_TYPE(base) {
11939 if (type->flags &
11940 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11941 /*
11942 * 2.1.3 only if the <extension> alternative is also
11943 * chosen, a simple type definition.
11944 */
11945 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11946 xmlSchemaPCustomErr(ctxt,
11947 XML_SCHEMAP_SRC_CT_1,
11948 NULL, type, NULL,
11949 "A complex type (simple content) cannot restrict "
11950 "an other simple type",
11951 NULL);
11952 return (XML_SCHEMAP_SRC_CT_1);
11953 }
11954 OK = 1;
11955
11956 } else { /* if IS_SIMPLE_TYPE(base) */
11957 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11958 /*
11959 * 2.1.2 only if the <restriction> alternative is also
11960 * chosen, a complex type definition whose {content type}
11961 * is mixed and a particle emptyable.
11962 */
11963 /*
11964 * FIXME TODO: Check for *empiable particle* is missing.
11965 */
11966 if ((type->flags &
11967 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11968 xmlSchemaPCustomErr(ctxt,
11969 XML_SCHEMAP_SRC_CT_1,
11970 NULL, type, NULL,
11971 "A complex type (simple content) cannot "
11972 "extend an other complex type which has a "
11973 "content type of: 'mixed' and emptiable particle",
11974 NULL);
11975 return (XML_SCHEMAP_SRC_CT_1);
11976 }
11977 /*
11978 * NOTE: This will be fired as well, if the base type
11979 * is *'anyType'*.
11980 * NOTE: type->subtypes->subtypes will be the
11981 * <restriction> item.
11982 */
11983 if (type->subtypes->subtypes == NULL) {
11984 /* Yes, this is paranoid programming. */
11985 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11986 NULL, type, NULL,
11987 "Internal error: xmlSchemaCheckSRCCT, "
11988 "'%s', <simpleContent> has no <restriction>",
11989 type->name);
11990 return (-1);
11991 }
11992 /*
11993 * 2.2 If clause 2.1.2 above is satisfied, then there
11994 * must be a <simpleType> among the [children] of
11995 * <restriction>.
11996 */
11997 if (type->subtypes->subtypes->type !=
11998 XML_SCHEMA_TYPE_SIMPLE) {
11999 /* TODO: Change error code to ..._SRC_CT_2_2. */
12000 xmlSchemaPCustomErr(ctxt,
12001 XML_SCHEMAP_SRC_CT_1,
12002 NULL, type, NULL,
12003 "A <simpleType> is expected among the children "
12004 "of <restriction>", NULL);
12005 return (XML_SCHEMAP_SRC_CT_1);
12006 }
12007 OK = 1;
12008 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12009 /*
12010 * 2.1.1 a complex type definition whose {content type} is a
12011 * simple type definition;
12012 */
12013 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12014 xmlSchemaPCustomErr(ctxt,
12015 XML_SCHEMAP_SRC_CT_1,
12016 NULL, type, NULL,
12017 "A complex type (simple content) cannot "
12018 "be derived from the complex type '%s'",
12019 base->name);
12020 return (XML_SCHEMAP_SRC_CT_1);
12021 }
12022 content = base->contentTypeDef;
12023 if (content == NULL) {
12024 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12025 NULL, type, NULL,
12026 "Internal error: xmlSchemaCheckSRCCT, "
12027 "'%s', base type has no content type",
12028 type->name);
12029 return (-1);
12030 }
12031 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12032 xmlSchemaPCustomErr(ctxt,
12033 XML_SCHEMAP_SRC_CT_1,
12034 NULL, type, NULL,
12035 "A complex type (simple content) cannot "
12036 "be derived from the complex type '%s'",
12037 base->name);
12038 return (XML_SCHEMAP_SRC_CT_1);
12039 }
12040 }
12041 }
12042 }
12043 }
12044 /*
12045 * TODO: 3 The corresponding complex type definition component must
12046 * satisfy the conditions set out in Constraints on Complex Type
12047 * Definition Schema Components (§3.4.6);
12048 *
12049 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12050 * above for {attribute wildcard} is satisfied, the intensional
12051 * intersection must be expressible, as defined in Attribute Wildcard
12052 * Intersection (§3.10.6).
12053 */
12054
12055}
William M. Brack2f2a6632004-08-20 23:09:47 +000012056#endif
12057
Daniel Veillard01fa6152004-06-29 17:04:39 +000012058/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012059 * xmlSchemaGroupDefFixup:
12060 * @typeDecl: the schema model group definition
12061 * @ctxt: the schema parser context
12062 *
12063 * Fixes model group definitions.
12064 */
12065static void
12066xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12067 xmlSchemaParserCtxtPtr ctxt,
12068 const xmlChar * name ATTRIBUTE_UNUSED)
12069{
12070 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12071 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12072 xmlSchemaTypePtr groupDef;
12073 /*
12074 * Resolve the reference.
12075 */
12076 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12077 group->refNs);
12078 if (groupDef == NULL) {
12079 xmlSchemaPResCompAttrErr(ctxt,
12080 XML_SCHEMAP_SRC_RESOLVE,
12081 NULL, group, NULL,
12082 "ref", group->ref, group->refNs,
12083 XML_SCHEMA_TYPE_GROUP, NULL);
12084 return;
12085 }
12086 group->subtypes = groupDef;
12087 }
12088}
12089
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012090#if 0 /* Enable when the content type will be computed. */
12091static int
12092xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12093 xmlSchemaTypePtr type)
12094{
12095 xmlSchemaTypePtr base, res = NULL;
12096
12097 base = type->baseType;
12098 if (base == NULL) {
12099 xmlSchemaPCustomErr(ctxt,
12100 XML_SCHEMAP_INTERNAL,
12101 NULL, type, NULL,
12102 "Internal error: xmlSchemaGetContentType, "
12103 "the complex type '%s' has no base type", type->name);
12104 return (-1);
12105 }
12106 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12107 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12108 xmlSchemaTypePtr start;
12109 /*
12110 * Effective 'mixed'.
12111 */
12112 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12113 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12114 /*
12115 * Effective content.
12116 */
12117 if (IS_ANYTYPE(base))
12118 start = type;
12119 else
12120 start = type->subtypes;
12121
12122 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12123 xmlSchemaTypePtr baseContentItem;
12124
12125 /*
12126 * Complex type with simple content.
12127 */
12128 if IS_COMPLEX_TYPE(base) {
12129 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12130 /*
12131 * Summary: a complex type (simple content) can *restrict*
12132 * a complex type with the following content type:
12133 * 1. 'mixed' and an emptiable particle
12134 * 2. simple type
12135 */
12136 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12137 /*
12138 * 2 if the {content type} of the base type is mixed and a
12139 * particle which is ·emptiable·,
12140 * [...]
12141 * then starting from the simple type definition
12142 * corresponding to the <simpleType> among the [children]
12143 * of <restriction> (**which must be present**)
12144 *
12145 * FIXME TODO: Handle "emptiable particle".
12146 */
12147 res = type->subtypes->subtypes;
12148 if (res == NULL) {
12149 xmlSchemaPCustomErr(ctxt,
12150 XML_SCHEMAP_INTERNAL,
12151 NULL, type, NULL,
12152 "Internal error: xmlSchemaGetContentType, "
12153 "CT '%s' (restricting): <simpleContent> has no "
12154 "<restriction>",
12155 type->name);
12156 return (-1);
12157 }
12158
12159 res->subtypes;
12160 if (res == NULL) {
12161 xmlSchemaPCustomErr(ctxt,
12162 XML_SCHEMAP_INTERNAL,
12163 NULL, type, NULL,
12164 "Internal error: xmlSchemaGetContentType, "
12165 "CT '%s' (restricting): <restriction> has no "
12166 "mandatory <simpleType>",
12167 type->name);
12168 return (-1);
12169 }
12170 } else {
12171 baseContentItem = base->contentTypeDef;
12172 if (baseContentItem == NULL) {
12173 xmlSchemaPCustomErr(ctxt,
12174 XML_SCHEMAP_INTERNAL,
12175 NULL, type, NULL,
12176 "Internal error: xmlSchemaGetContentType, "
12177 "CT '%s' (restricting), the base type has no "
12178 "content type", type->name);
12179 return (-1);
12180 }
12181 if IS_SIMPLE_TYPE(baseContentItem) {
12182 /*
12183 * 1 If the base type is a complex type whose own
12184 * {content type} is a simple type and the <restriction>
12185 * alternative is chosen
12186 */
12187 /* type->subtypes->subtypes will be the restriction item.*/
12188 res = type->subtypes->subtypes;
12189 if (res == NULL) {
12190 xmlSchemaPCustomErr(ctxt,
12191 XML_SCHEMAP_INTERNAL,
12192 NULL, type, NULL,
12193 "Internal error: xmlSchemaGetContentType, "
12194 "CT '%s' (restricting): <simpleType> has no "
12195 "<restriction>", type->name);
12196 return (-1);
12197 }
12198 /*
12199 * 1.1 the simple type definition corresponding to the
12200 * <simpleType> among the [children] of <restriction>if
12201 * there is one;
12202 */
12203 res = res->subtypes;
12204 if (res == NULL) {
12205 /*
12206 * 1.2 otherwise the {content type}
12207 * of the base type .
12208 */
12209 res = baseContentItem;
12210 }
12211 }
12212 }
12213 /*
12214 * SPECIAL TODO: If *restricting* the spec wants us to
12215 * create an *additional* simple type which restricts the
12216 * located simple type; we won't do this yet, and look how
12217 * far we get with it.
12218 */
12219 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12220 /*
12221 * Summary: a complex type (simple content) can *extend*
12222 * only a complex base with a simple type as content.
12223 */
12224 /*
12225 * 3 If the type definition ·resolved· to by the ·actual
12226 * value· of the base [attribute] is a complex type
12227 * definition (whose own {content type} *must be* a simple
12228 * type definition, see below) and the *<extension>*
12229 * alternative is chosen, then the {content type} of that
12230 * complex type definition;
12231 */
12232 res = base->contentTypeDef;
12233 if (res == NULL) {
12234 xmlSchemaPCustomErr(ctxt,
12235 XML_SCHEMAP_INTERNAL,
12236 NULL, type, NULL,
12237 "Internal error: xmlSchemaGetContentType, "
12238 "CT '%s' (extending), the base type has no content "
12239 "type", type->name);
12240 return (-1);
12241 }
12242 if (! IS_SIMPLE_TYPE(res)) {
12243 xmlSchemaPCustomErr(ctxt,
12244 XML_SCHEMAP_INTERNAL,
12245 NULL, type, NULL,
12246 "Internal error: xmlSchemaGetContentType, "
12247 "CT '%s' (extending), the content type of the "
12248 "base is not a simple type", type->name);
12249 return (-1);
12250 }
12251 }
12252 } else /* if IS_COMPLEX_TYPE(base) */
12253 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12254 /*
12255 * 4 otherwise (the type definition ·resolved· to by the
12256 * ·actual value· of the base [attribute] is a simple type
12257 * definition and the <extension> alternative is chosen),
12258 * then that simple type definition.
12259 */
12260 res = base;
12261 }
12262 type->contentTypeDef = res;
12263 if (res == NULL) {
12264 xmlSchemaPCustomErr(ctxt,
12265 XML_SCHEMAP_INTERNAL,
12266 NULL, type, NULL,
12267 "Internal error: xmlSchemaGetContentType, "
12268 "'%s', the content type could not be determined",
12269 type->name);
12270 return (-1);
12271 }
12272
12273 }
12274
12275}
12276#endif
12277
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012278/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012279 * xmlSchemaTypeFixup:
12280 * @typeDecl: the schema type definition
12281 * @ctxt: the schema parser context
12282 *
12283 * Fixes the content model of the type.
12284 */
12285static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012286xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012287 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012288{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012289 xmlSchemaTypePtr ctxtType;
12290
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012291 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012292 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012293 /*
12294 * Do not allow the following types to be typefixed, prior to
12295 * the corresponding simple/complex types.
12296 */
12297 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012298 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012299 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12300 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12301 case XML_SCHEMA_TYPE_UNION:
12302 case XML_SCHEMA_TYPE_RESTRICTION:
12303 case XML_SCHEMA_TYPE_EXTENSION:
12304 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012305 default:
12306 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012307 }
12308 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012309 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012310 name = item->name;
12311 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12312 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012313 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012314 if (item->subtypes != NULL) {
12315 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012316 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012317 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012318 NULL);
12319 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012320 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012321 XML_SCHEMA_CONTENT_SIMPLE;
12322 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012323 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012324 break;
12325 }
12326 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012327 xmlSchemaTypePtr base = NULL;
12328
12329 ctxt->ctxtType->flags |=
12330 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012331 if (item->baseType != NULL)
12332 base = item->baseType;
12333 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012334 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012335 xmlSchemaGetType(ctxt->schema, item->base,
12336 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012337 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012338 xmlSchemaPResCompAttrErr(ctxt,
12339 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012340 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012341 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12342 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012343 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012344 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012345 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012346 xmlSchemaTypeFixup(base, ctxt, NULL);
12347 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012348 }
12349 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012350 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12351 /*
12352 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012353 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012354 /*
12355 * Content type.
12356 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012357 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012358 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012359 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12360 else if ((item->subtypes->subtypes == NULL) &&
12361 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012362 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012363 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 XML_SCHEMA_TYPE_SEQUENCE)))
12365 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012366 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12367 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012368 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012369 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012370 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012371 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012372 else {
12373 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012374 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012375 XML_SCHEMA_CONTENT_ELEMENTS;
12376 }
12377 } else {
12378 /*
12379 * SimpleType restriction.
12380 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012381 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012382 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012383 break;
12384 }
12385 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012386 xmlSchemaTypePtr base = NULL;
12387 xmlSchemaContentType explicitContentType;
12388
12389 /*
12390 * An extension does exist on a complexType only.
12391 */
12392 ctxt->ctxtType->flags |=
12393 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012394 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012395 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012396 xmlSchemaPCustomErr(ctxt,
12397 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012398 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012399 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012400 return;
12401 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012402 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012403 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012404 xmlSchemaGetType(ctxt->schema, item->base,
12405 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012406 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012407 xmlSchemaPResCompAttrErr(ctxt,
12408 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012409 NULL, item, item->node,
12410 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012411 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012412 } else if (base->contentType ==
12413 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012414 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012415 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012417 }
12418 /*
12419 * The type definition ·resolved· to by the ·actual
12420 * value· of the base [attribute]
12421 */
12422 ctxt->ctxtType->baseType = base;
12423 /*
12424 * TODO: This one is still needed for computation of
12425 * the content model by xmlSchemaBuildAContentModel.
12426 * Try to get rid of it.
12427 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012428 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012429 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012430 if ((item->subtypes != NULL) &&
12431 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12432 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012433
12434 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012435 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012436 /* 1.1.1 */
12437 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012438 else if ((item->subtypes->subtypes == NULL) &&
12439 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012440 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012441 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012442 XML_SCHEMA_TYPE_SEQUENCE)))
12443 /* 1.1.2 */
12444 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012445 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012446 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012447 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012448 /* 1.1.3 */
12449 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12450 if (base != NULL) {
12451 /* It will be reported later, if the base is missing. */
12452 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12453 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012454 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012455 } else if (base->contentType ==
12456 XML_SCHEMA_CONTENT_EMPTY) {
12457 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012458 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012459 XML_SCHEMA_CONTENT_ELEMENTS;
12460 } else {
12461 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012462 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012463 XML_SCHEMA_CONTENT_ELEMENTS;
12464 }
12465 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012466 break;
12467 }
12468 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012469 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012470 ctxt->ctxtType = item;
12471 /*
12472 * Start with an empty content-type type.
12473 */
12474 if (item->subtypes == NULL)
12475 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12476
12477 if ((item->subtypes == NULL) ||
12478 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012479 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012480 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012481 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12482 /*
12483 * This case is understood as shorthand for complex
12484 * content restricting the ur-type definition, and
12485 * the details of the mappings should be modified as
12486 * necessary.
12487 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012488 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12489 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012490 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012491 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012492 * Assume that we inherit the content-type type
12493 * from 'anyType', which is 'mixed' and a particle
12494 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012495 */
12496 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012497 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012498 /*
12499 * Fixup the sub components.
12500 */
12501 if ((item->subtypes != NULL) &&
12502 (item->subtypes->contentType ==
12503 XML_SCHEMA_CONTENT_UNKNOWN)) {
12504 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012505 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012506 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12507 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12508 } else if (item->subtypes != NULL) {
12509 /*
12510 * Use the content-type type of the model groups
12511 * defined, if 'mixed' is not set. If 'mixed' is set
12512 * it will expand the content-type by allowing character
12513 * content to appear.
12514 */
12515 item->contentType =
12516 item->subtypes->contentType;
12517 }
12518 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012519 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012520 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012521 break;
12522 }
12523 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012524 if (item->subtypes == NULL) {
12525 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12526 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12527 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012528 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012529 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012530 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12531 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012532 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012533 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012534 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012535 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012536 if (item->subtypes != NULL)
12537 item->contentType =
12538 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012539 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012540 /*
12541 * Removed due to implementation of the build of attribute uses.
12542 */
12543 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012544 if (item->attributes == NULL)
12545 item->attributes =
12546 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012547 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012548 }
12549 break;
12550 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012551 case XML_SCHEMA_TYPE_SIMPLE:
12552 /*
12553 * Simple Type Definition Schema Component
12554 *
12555 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012556 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012557 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12558 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012559 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012560 ctxt->ctxtType = item;
12561 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012562 }
12563 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012564 if ((item->baseType != NULL) &&
12565 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012566 XML_SCHEMA_CONTENT_UNKNOWN)) {
12567 /* OPTIMIZE: Actually this one will never by hit, since
12568 * the base type is already type-fixed in <restriction>.
12569 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012570 ctxt->ctxtType = item;
12571 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012572 }
12573 /* Base type:
12574 * 2 If the <list> or <union> alternative is chosen,
12575 * then the ·simple ur-type definition·.
12576 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012577 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012578 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012579 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12580 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12581 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012582 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012583 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12584 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12585 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012586 XML_SCHEMA_TYPE_RESTRICTION) {
12587 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12588
12589 /*
12590 * Variety
12591 * If the <restriction> alternative is chosen, then the
12592 * {variety} of the {base type definition}.
12593 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012594 if (item->baseType != NULL) {
12595 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012596 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012597 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12598 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012599 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012600 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12601 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012602 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012603 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012604 /*
12605 * Schema Component Constraint: Simple Type Restriction
12606 * (Facets)
12607 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12608 * applied beforehand.
12609 *
12610 * 3 The {facets} of R are the union of S and the {facets}
12611 * of B, eliminating duplicates. To eliminate duplicates,
12612 * when a facet of the same kind occurs in both S and the
12613 * {facets} of B, the one in the {facets} of B is not
12614 * included, with the exception of enumeration and pattern
12615 * facets, for which multiple occurrences with distinct values
12616 * are allowed.
12617 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012618 if (item->baseType->facetSet != NULL) {
12619 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012620 if (last != NULL)
12621 while (last->next != NULL)
12622 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012623 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012624 for (; cur != NULL; cur = cur->next) {
12625 /*
12626 * Base patterns won't be add here:
12627 * they are ORed in a type and
12628 * ANDed in derived types. This will
12629 * happed at validation level by
12630 * walking the base axis of the type.
12631 */
12632 if (cur->facet->type ==
12633 XML_SCHEMA_FACET_PATTERN)
12634 continue;
12635 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012636 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012637 (cur->facet->type !=
12638 XML_SCHEMA_FACET_PATTERN) &&
12639 (cur->facet->type !=
12640 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012641 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012642 do {
12643 if (cur->facet->type ==
12644 facet->facet->type)
12645 break;
12646 facet = facet->next;
12647 } while (facet != NULL);
12648 }
12649 if (facet == NULL) {
12650 facet = (xmlSchemaFacetLinkPtr)
12651 xmlMalloc(sizeof(xmlSchemaFacetLink));
12652 if (facet == NULL) {
12653 xmlSchemaPErrMemory(ctxt,
12654 "fixing simpleType", NULL);
12655 return;
12656 }
12657 facet->facet = cur->facet;
12658 facet->next = NULL;
12659 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012660 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012661 else
12662 last->next = facet;
12663 last = facet;
12664 }
12665 }
12666 }
12667 }
12668 }
12669 /*
12670 * Check constraints.
12671 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012672 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012673 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012674 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012675 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012676 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012677 case XML_SCHEMA_TYPE_ALL:
12678 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012679 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012680 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012681 case XML_SCHEMA_TYPE_GROUP:
12682 /*
12683 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12684 */
12685 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012686 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012687 xmlSchemaParseListRefFixup(item, ctxt);
12688 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012689 break;
12690 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012691 xmlSchemaParseUnionRefCheck(item, ctxt);
12692 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012693 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012694 case XML_SCHEMA_TYPE_BASIC:
12695 case XML_SCHEMA_TYPE_ANY:
12696 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012697 case XML_SCHEMA_TYPE_UR:
12698 case XML_SCHEMA_TYPE_ELEMENT:
12699 case XML_SCHEMA_TYPE_ATTRIBUTE:
12700 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012701 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012702 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012703 case XML_SCHEMA_FACET_MININCLUSIVE:
12704 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12705 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12706 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12707 case XML_SCHEMA_FACET_TOTALDIGITS:
12708 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12709 case XML_SCHEMA_FACET_PATTERN:
12710 case XML_SCHEMA_FACET_ENUMERATION:
12711 case XML_SCHEMA_FACET_WHITESPACE:
12712 case XML_SCHEMA_FACET_LENGTH:
12713 case XML_SCHEMA_FACET_MAXLENGTH:
12714 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012715 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12716 if (item->subtypes != NULL)
12717 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012718 break;
12719 }
12720 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012721#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012722 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012723 xmlGenericError(xmlGenericErrorContext,
12724 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012725 item->node->doc->URL,
12726 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012727 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012728 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012729 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012730 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012731 case XML_SCHEMA_CONTENT_SIMPLE:
12732 xmlGenericError(xmlGenericErrorContext, "simple\n");
12733 break;
12734 case XML_SCHEMA_CONTENT_ELEMENTS:
12735 xmlGenericError(xmlGenericErrorContext, "elements\n");
12736 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012737 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012738 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12739 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012740 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012741 xmlGenericError(xmlGenericErrorContext, "empty\n");
12742 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012743 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012744 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12745 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012746 /* Removed, since not used. */
12747 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012748 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012749 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12750 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012751 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012752 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012753 xmlGenericError(xmlGenericErrorContext, "basic\n");
12754 break;
12755 default:
12756 xmlGenericError(xmlGenericErrorContext,
12757 "not registered !!!\n");
12758 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012759 }
12760#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012761}
12762
12763/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012764 * xmlSchemaCheckFacet:
12765 * @facet: the facet
12766 * @typeDecl: the schema type definition
12767 * @ctxt: the schema parser context or NULL
12768 * @name: name of the type
12769 *
12770 * Checks the default values types, especially for facets
12771 *
12772 * Returns 0 if okay or -1 in cae of error
12773 */
12774int
12775xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012776 xmlSchemaTypePtr typeDecl,
12777 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012778{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012779 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012780 int ret = 0, reuseValCtxt = 0;
12781
Daniel Veillardce682bc2004-11-05 17:22:25 +000012782 if ((facet == NULL) || (typeDecl == NULL))
12783 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012784 /*
12785 * TODO: will the parser context be given if used from
12786 * the relaxNG module?
12787 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012788
12789 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012790 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012791 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012792 }
12793 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012794 case XML_SCHEMA_FACET_MININCLUSIVE:
12795 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12796 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012797 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12798 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012799 /*
12800 * Okay we need to validate the value
12801 * at that point.
12802 */
12803 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012804 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012805
12806 /* 4.3.5.5 Constraints on enumeration Schema Components
12807 * Schema Component Constraint: enumeration valid restriction
12808 * It is an ·error· if any member of {value} is not in the
12809 * ·value space· of {base type definition}.
12810 *
12811 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12812 * The value ·must· be in the
12813 * ·value space· of the ·base type·.
12814 */
12815 /*
12816 * This function is intended to deliver a compiled value
12817 * on the facet. In XML Schemas the type holding a facet,
12818 * cannot be a built-in type. Thus to ensure that other API
12819 * calls (relaxng) do work, if the given type is a built-in
12820 * type, we will assume that the given built-in type *is
12821 * already* the base type.
12822 */
12823 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12824 base = typeDecl->baseType;
12825 if (base == NULL) {
12826 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012827 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012828 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012829 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012830 typeDecl->name, NULL);
12831 return (-1);
12832 }
12833 } else
12834 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012835 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012836 * This avoids perseverative creation of the
12837 * validation context if a parser context is
12838 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012839 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012840 if (ctxt != NULL) {
12841 reuseValCtxt = 1;
12842 if (ctxt->vctxt == NULL) {
12843 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12844 return (-1);
12845 }
12846 vctxt = ctxt->vctxt;
12847 } else {
12848 vctxt = xmlSchemaNewValidCtxt(NULL);
12849 if (vctxt == NULL) {
12850 xmlSchemaPErr(ctxt, typeDecl->node,
12851 XML_SCHEMAP_INTERNAL,
12852 "Internal error: xmlSchemaCheckFacet, "
12853 "creating a new validation context.\n",
12854 NULL, NULL);
12855 return (-1);
12856 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012857 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012858
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012859 vctxt->node = facet->node;
12860 vctxt->cur = NULL;
12861 /*
12862 * NOTE: This call does not check the content nodes,
12863 * since they are not available:
12864 * facet->node is just the node holding the facet
12865 * definition, *not* the attribute holding the *value*
12866 * of the facet.
12867 */
12868 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12869 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012870 facet->val = vctxt->value;
12871 vctxt->value = NULL;
12872 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012873 /* error code */
12874 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012875 xmlSchemaPErrExt(ctxt, facet->node,
12876 XML_SCHEMAP_INVALID_FACET,
12877 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012878 "Type definition '%s': The value '%s' of the "
12879 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012880 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012881 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012882 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012883 }
12884 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012885 } else if (ret < 0) {
12886 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012887 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012888 NULL, NULL, NULL,
12889 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012890 "failed to validate the value '%s' name of the "
12891 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012892 facet->value,
12893 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12894 base->name, NULL, NULL);
12895 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012896 }
12897 if (reuseValCtxt == 0)
12898 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012899 break;
12900 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012901 case XML_SCHEMA_FACET_PATTERN:
12902 facet->regexp = xmlRegexpCompile(facet->value);
12903 if (facet->regexp == NULL) {
12904 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012905 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012906 "Type definition '%s': The value '%s' of the "
12907 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012908 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012909 ret = -1;
12910 }
12911 break;
12912 case XML_SCHEMA_FACET_TOTALDIGITS:
12913 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12914 case XML_SCHEMA_FACET_LENGTH:
12915 case XML_SCHEMA_FACET_MAXLENGTH:
12916 case XML_SCHEMA_FACET_MINLENGTH:{
12917 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012918
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012919 tmp =
12920 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12921 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012922 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012923 if (tmp != 0) {
12924 /* error code */
12925 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012926 xmlSchemaPErrExt(ctxt, facet->node,
12927 XML_SCHEMAP_INVALID_FACET_VALUE,
12928 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012929 "Type definition '%s': The value '%s' of the "
12930 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012931 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012932 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012933 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012934 }
12935 ret = -1;
12936 }
12937 break;
12938 }
12939 case XML_SCHEMA_FACET_WHITESPACE:{
12940 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12941 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12942 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12943 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12944 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12945 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12946 } else {
12947 if (ctxt != NULL) {
12948 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012949 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012950 "Type definition '%s': The value '%s' of the "
12951 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012952 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012953 }
12954 ret = -1;
12955 }
12956 }
12957 default:
12958 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012959 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012960 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012961}
12962
12963/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012964 * xmlSchemaCheckDefaults:
12965 * @typeDecl: the schema type definition
12966 * @ctxt: the schema parser context
12967 *
12968 * Checks the default values types, especially for facets
12969 */
12970static void
12971xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012972 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012973{
Daniel Veillard4255d502002-04-16 15:50:10 +000012974 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012975 name = typeDecl->name;
12976 /*
12977 * NOTE: It is intended to use the facets list, instead
12978 * of facetSet.
12979 */
12980 if (typeDecl->facets != NULL) {
12981 xmlSchemaFacetPtr facet = typeDecl->facets;
12982
12983 while (facet != NULL) {
12984 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12985 facet = facet->next;
12986 }
12987 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012988}
12989
12990/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012991 * xmlSchemaGetCircModelGrDefRef:
12992 * @ctxtGr: the searched model group
12993 * @list: the list of model groups to be processed
12994 *
12995 * This one is intended to be used by
12996 * xmlSchemaCheckGroupDefCircular only.
12997 *
12998 * Returns the circular model group definition reference, otherwise NULL.
12999 */
13000static xmlSchemaTypePtr
13001xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13002 xmlSchemaTypePtr gr)
13003{
13004 xmlSchemaTypePtr circ = NULL;
13005 int marked;
13006 /*
13007 * We will search for an model group reference which
13008 * references the context model group definition.
13009 */
13010 while (gr != NULL) {
13011 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13012 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13013 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13014 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13015 (gr->subtypes != NULL)) {
13016 marked = 0;
13017 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13018 (gr->ref != NULL)) {
13019 if (gr->subtypes == ctxtGrDef)
13020 return (gr);
13021 else if (gr->subtypes->flags &
13022 XML_SCHEMAS_TYPE_MARKED) {
13023 gr = gr->next;
13024 continue;
13025 } else {
13026 /*
13027 * Mark to avoid infinite recursion on
13028 * circular references not yet examined.
13029 */
13030 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13031 marked = 1;
13032 }
13033 if (gr->subtypes->subtypes != NULL)
13034 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13035 gr->subtypes->subtypes);
13036 /*
13037 * Unmark the visited model group definition.
13038 */
13039 if (marked)
13040 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13041 if (circ != NULL)
13042 return (circ);
13043 } else {
13044 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13045 (xmlSchemaTypePtr) gr->subtypes);
13046 if (circ != NULL)
13047 return (circ);
13048 }
13049
13050 }
13051 gr = gr->next;
13052 }
13053 return (NULL);
13054}
13055
13056/**
13057 * xmlSchemaCheckGroupDefCircular:
13058 * attrGr: the model group definition
13059 * @ctxt: the parser context
13060 * @name: the name
13061 *
13062 * Checks for circular references to model group definitions.
13063 */
13064static void
13065xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13066 xmlSchemaParserCtxtPtr ctxt,
13067 const xmlChar * name ATTRIBUTE_UNUSED)
13068{
13069 /*
13070 * Schema Component Constraint: Model Group Correct
13071 * 2 Circular groups are disallowed. That is, within the {particles}
13072 * of a group there must not be at any depth a particle whose {term}
13073 * is the group itself.
13074 */
13075 /*
13076 * NOTE: "gr->subtypes" holds the referenced group.
13077 */
13078 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13079 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13080 (modelGrDef->subtypes == NULL))
13081 return;
13082 else {
13083 xmlSchemaTypePtr circ;
13084
13085 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13086 if (circ != NULL) {
13087 /*
13088 * TODO: Report the referenced attr group as QName.
13089 */
13090 xmlSchemaPCustomErr(ctxt,
13091 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13092 NULL, NULL, circ->node,
13093 "Circular reference to the model group definition '%s' "
13094 "defined", modelGrDef->name);
13095 /*
13096 * NOTE: We will cut the reference to avoid further
13097 * confusion of the processor.
13098 * TODO: SPEC: Does the spec define how to process here?
13099 */
13100 circ->subtypes = NULL;
13101 }
13102 }
13103}
13104
13105
13106/**
13107 * xmlSchemaGetCircAttrGrRef:
13108 * @ctxtGr: the searched attribute group
13109 * @attr: the current attribute list to be processed
13110 *
13111 * This one is intended to be used by
13112 * xmlSchemaCheckSRCAttributeGroupCircular only.
13113 *
13114 * Returns the circular attribute grou reference, otherwise NULL.
13115 */
13116static xmlSchemaAttributeGroupPtr
13117xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
13118 xmlSchemaAttributePtr attr)
13119{
13120 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13121 int marked;
13122 /*
13123 * We will search for an attribute group reference which
13124 * references the context attribute group.
13125 */
13126 while (attr != NULL) {
13127 marked = 0;
13128 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13129 gr = (xmlSchemaAttributeGroupPtr) attr;
13130 if (gr->refItem != NULL) {
13131 if (gr->refItem == ctxtGr)
13132 return (gr);
13133 else if (gr->refItem->flags &
13134 XML_SCHEMAS_ATTRGROUP_MARKED) {
13135 attr = attr->next;
13136 continue;
13137 } else {
13138 /*
13139 * Mark as visited to avoid infinite recursion on
13140 * circular references not yet examined.
13141 */
13142 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
13143 marked = 1;
13144 }
13145 }
13146 if (gr->attributes != NULL)
13147 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
13148 /*
13149 * Unmark the visited group's attributes.
13150 */
13151 if (marked)
13152 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
13153 if (circ != NULL)
13154 return (circ);
13155 }
13156 attr = attr->next;
13157 }
13158 return (NULL);
13159}
13160
13161/**
13162 * xmlSchemaCheckSRCAttributeGroupCircular:
13163 * attrGr: the attribute group definition
13164 * @ctxt: the parser context
13165 * @name: the name
13166 *
13167 * Checks for circular references of attribute groups.
13168 */
13169static void
13170xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
13171 xmlSchemaParserCtxtPtr ctxt,
13172 const xmlChar * name ATTRIBUTE_UNUSED)
13173{
13174 /*
13175 * Schema Representation Constraint:
13176 * Attribute Group Definition Representation OK
13177 * 3 Circular group reference is disallowed outside <redefine>.
13178 * That is, unless this element information item's parent is
13179 * <redefine>, then among the [children], if any, there must
13180 * not be an <attributeGroup> with ref [attribute] which resolves
13181 * to the component corresponding to this <attributeGroup>. Indirect
13182 * circularity is also ruled out. That is, when QName resolution
13183 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13184 * any <attributeGroup>s with a ref [attribute] among the [children],
13185 * it must not be the case that a ·QName· is encountered at any depth
13186 * which resolves to the component corresponding to this <attributeGroup>.
13187 */
13188 /*
13189 * Only global components can be referenced.
13190 */
13191 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
13192 (attrGr->attributes == NULL))
13193 return;
13194 else {
13195 xmlSchemaAttributeGroupPtr circ;
13196
13197 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
13198 if (circ != NULL) {
13199 /*
13200 * TODO: Report the referenced attr group as QName.
13201 */
13202 xmlSchemaPCustomErr(ctxt,
13203 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13204 NULL, NULL, circ->node,
13205 "Circular reference to the attribute group '%s' "
13206 "defined", attrGr->name);
13207 /*
13208 * NOTE: We will cut the reference to avoid further
13209 * confusion of the processor.
13210 * BADSPEC: The spec should define how to process in this case.
13211 */
13212 circ->attributes = NULL;
13213 circ->refItem = NULL;
13214 }
13215 }
13216}
13217
13218/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013219 * xmlSchemaAttrGrpFixup:
13220 * @attrgrpDecl: the schema attribute definition
13221 * @ctxt: the schema parser context
13222 * @name: the attribute name
13223 *
13224 * Fixes finish doing the computations on the attributes definitions
13225 */
13226static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013227xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013228 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013229{
13230 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013231 name = attrgrp->name;
13232 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013233 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013234 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013235 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013236
Daniel Veillardc0826a72004-08-10 14:17:33 +000013237 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13238 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013239 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013240 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013241 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013242 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13243 "ref", attrgrp->ref, attrgrp->refNs,
13244 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013245 return;
13246 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013247 attrgrp->refItem = ref;
13248 /*
13249 * Check for self reference!
13250 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013251 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013252 attrgrp->attributes = ref->attributes;
13253 attrgrp->attributeWildcard = ref->attributeWildcard;
13254 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013255}
13256
13257/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013258 * xmlSchemaAttrCheckValConstr:
13259 * @item: an schema attribute declaration/use
13260 * @ctxt: a schema parser context
13261 * @name: the name of the attribute
13262 *
13263 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013264 *
13265 * Fixes finish doing the computations on the attributes definitions
13266 */
13267static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013268xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13269 xmlSchemaParserCtxtPtr ctxt,
13270 const xmlChar * name ATTRIBUTE_UNUSED)
13271{
13272
13273 /*
13274 * a-props-correct
13275 * Schema Component Constraint: Attribute Declaration Properties Correct
13276 *
13277 * 2 if there is a {value constraint}, the canonical lexical
13278 * representation of its value must be ·valid· with respect
13279 * to the {type definition} as defined in String Valid (§3.14.4).
13280 */
13281
13282 if (item->defValue != NULL) {
13283 int ret;
13284 xmlNodePtr node;
13285 xmlSchemaTypePtr type;
13286
13287 if (item->subtypes == NULL) {
13288 xmlSchemaPErr(ctxt, item->node,
13289 XML_SCHEMAP_INTERNAL,
13290 "Internal error: xmlSchemaCheckAttrValConstr, "
13291 "type is missing... skipping validation of "
13292 "value constraint", NULL, NULL);
13293 return;
13294 }
13295
13296 /*
13297 * TODO: Try to avoid creating a new context.
13298 * TODO: This all is not very performant.
13299 */
13300 type = item->subtypes;
13301 /*
13302 * Ensure there's validation context.
13303 */
13304 if (ctxt->vctxt == NULL) {
13305 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13306 xmlSchemaPErr(ctxt, item->node,
13307 XML_SCHEMAP_INTERNAL,
13308 "Internal error: xmlSchemaCheckAttrValConstr, "
13309 "creating a new validation context.\n",
13310 NULL, NULL);
13311 return;
13312 }
13313 }
13314
13315 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13316 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13317 else
13318 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13319 ctxt->vctxt->node = node;
13320 ctxt->vctxt->cur = NULL;
13321 /*
13322 * NOTE: This call does not check the content nodes,
13323 * since they are not available:
13324 * facet->node is just the node holding the facet
13325 * definition, *not* the attribute holding the *value*
13326 * of the facet.
13327 */
13328 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13329 item->defValue, 0, 1, 1, 0);
13330 if (ret == 0) {
13331 /*
13332 * Store the computed value.
13333 */
13334 item->defVal = ctxt->vctxt->value;
13335 ctxt->vctxt->value = NULL;
13336 } else if (ret > 0) {
13337 if (ctxt != NULL) {
13338 xmlSchemaPSimpleTypeErr(ctxt,
13339 XML_SCHEMAP_A_PROPS_CORRECT_2,
13340 NULL, NULL, node,
13341 type, NULL, item->defValue,
13342 NULL, NULL, NULL);
13343 }
13344 } else if (ret < 0) {
13345 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13346 NULL, NULL, node,
13347 "Internal error: xmlSchemaAttrCheckValConstr, "
13348 "failed to validate the value constraint of the "
13349 "attribute decl/use against the type '%s'",
13350 type->name);
13351 }
13352 }
13353}
13354
13355#if 0 /* Not used yet. */
13356static int
13357xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13358 xmlSchemaElementPtr edecl)
13359{
13360 /*
13361 * TODO: 1 The values of the properties of an element declaration must be as
13362 * described in the property tableau in The Element Declaration Schema
13363 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13364 */
13365 /*
13366 * 2 If there is a {value constraint}, the canonical lexical
13367 * representation of its value must be ·valid· with respect to the {type
13368 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13369 *
13370 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13371 */
13372 /*
13373 * 3 If there is a non-·absent· {substitution group affiliation},
13374 * then {scope} must be global.
13375 *
13376 * NOTE: This is done in xmlSchemaParseElement.
13377 * TODO: Move it to this layer here.
13378 */
13379 /*
13380 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13381 * of the element declaration must be validly derived from the {type
13382 * definition} of the {substitution group affiliation}, given the value
13383 * of the {substitution group exclusions} of the {substitution group
13384 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13385 * (if the {type definition} is complex) or as defined in
13386 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13387 * simple).
13388 */
13389 /*
13390 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13391 * is or is derived from ID then there must not be a {value constraint}.
13392 * Note: The use of ID as a type definition for elements goes beyond
13393 * XML 1.0, and should be avoided if backwards compatibility is desired
13394 */
13395 /*
13396 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13397 * be possible to return to an element declaration by repeatedly following
13398 * the {substitution group affiliation} property.
13399 */
13400}
13401#endif
13402
13403/**
13404 * xmlSchemaCheckElemValConstr:
13405 * @item: an schema element declaration/particle
13406 * @ctxt: a schema parser context
13407 * @name: the name of the attribute
13408 *
13409 * Validates the value constraints of an element declaration.
13410 *
13411 * Fixes finish doing the computations on the element declarations.
13412 */
13413static void
13414xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13415 xmlSchemaParserCtxtPtr ctxt,
13416 const xmlChar * name ATTRIBUTE_UNUSED)
13417{
13418 if (decl->value != NULL) {
13419 int ret;
13420 xmlNodePtr node = NULL;
13421 xmlSchemaTypePtr type;
13422
13423 /*
13424 * 2 If there is a {value constraint}, the canonical lexical
13425 * representation of its value must be ·valid· with respect to the {type
13426 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13427 */
13428 if (decl->subtypes == NULL) {
13429 xmlSchemaPErr(ctxt, decl->node,
13430 XML_SCHEMAP_INTERNAL,
13431 "Internal error: xmlSchemaCheckElemValConstr, "
13432 "type is missing... skipping validation of "
13433 "the value constraint", NULL, NULL);
13434 return;
13435 }
13436 /*
13437 * Ensure there's a validation context.
13438 */
13439 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13440 return;
13441
13442 type = decl->subtypes;
13443
13444 if (decl->node != NULL) {
13445 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13446 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13447 else
13448 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13449 }
13450 ctxt->vctxt->node = node;
13451 ctxt->vctxt->cur = NULL;
13452 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13453 node);
13454 if (ret == 0) {
13455 /*
13456 * Consume the computed value.
13457 */
13458 decl->defVal = ctxt->vctxt->value;
13459 ctxt->vctxt->value = NULL;
13460 } else if (ret < 0) {
13461 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13462 NULL, NULL, node,
13463 "Internal error: xmlSchemaElemCheckValConstr, "
13464 "failed to validate the value constraint of the "
13465 "element declaration '%s'",
13466 decl->name);
13467 }
13468 }
13469}
13470
13471/**
13472 * xmlSchemaAttrFixup:
13473 * @item: an schema attribute declaration/use.
13474 * @ctxt: a schema parser context
13475 * @name: the name of the attribute
13476 *
13477 * Fixes finish doing the computations on attribute declarations/uses.
13478 */
13479static void
13480xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13481 xmlSchemaParserCtxtPtr ctxt,
13482 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013483{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013484 /*
13485 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013486 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013487 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013488 /*
13489 * The simple type definition corresponding to the <simpleType> element
13490 * information item in the [children], if present, otherwise the simple
13491 * type definition ·resolved· to by the ·actual value· of the type
13492 * [attribute], if present, otherwise the ·simple ur-type definition·.
13493 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013494 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013495 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013496 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13497 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013498 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013499 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013500 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013501
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013502 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13503 item->typeNs);
13504 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013505 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013507 NULL, (xmlSchemaTypePtr) item, item->node,
13508 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013509 XML_SCHEMA_TYPE_SIMPLE, NULL);
13510 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013511 item->subtypes = type;
13512
13513 } else if (item->ref != NULL) {
13514 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013515
Daniel Veillardc0826a72004-08-10 14:17:33 +000013516 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013517 * We have an attribute use here; assign the referenced
13518 * attribute declaration.
13519 */
13520 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013521 * TODO: Evaluate, what errors could occur if the declaration is not
13522 * found. It might be possible that the "typefixup" might crash if
13523 * no ref declaration was found.
13524 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013525 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13526 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013527 xmlSchemaPResCompAttrErr(ctxt,
13528 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013529 NULL, (xmlSchemaTypePtr) item, item->node,
13530 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013531 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013532 return;
13533 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013534 item->refDecl = decl;
13535 xmlSchemaAttrFixup(decl, ctxt, NULL);
13536
13537 item->subtypes = decl->subtypes;
13538 /*
13539 * Attribute Use Correct
13540 * au-props-correct.2: If the {attribute declaration} has a fixed
13541 * {value constraint}, then if the attribute use itself has a
13542 * {value constraint}, it must also be fixed and its value must match
13543 * that of the {attribute declaration}'s {value constraint}.
13544 */
13545 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13546 (item->defValue != NULL)) {
13547 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13548 (!xmlStrEqual(item->defValue, decl->defValue))) {
13549 xmlSchemaPCustomErr(ctxt,
13550 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13551 NULL, NULL, item->node,
13552 "The value constraint must be fixed "
13553 "and match the referenced attribute "
13554 "declarations's value constraint '%s'",
13555 decl->defValue);
13556 }
13557 /*
13558 * FUTURE: One should change the values of the attr. use
13559 * if ever validation should be attempted even if the
13560 * schema itself was not fully valid.
13561 */
13562 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013563 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013564 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13565 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013566}
13567
13568/**
13569 * xmlSchemaParse:
13570 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013571 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013572 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013573 * XML Shema struture which can be used to validate instances.
13574 * *WARNING* this interface is highly subject to change
13575 *
13576 * Returns the internal XML Schema structure built from the resource or
13577 * NULL in case of error
13578 */
13579xmlSchemaPtr
13580xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13581{
13582 xmlSchemaPtr ret = NULL;
13583 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013584 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013585 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013586
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013587 /*
13588 * This one is used if the schema to be parsed was specified via
13589 * the API; i.e. not automatically by the validated instance document.
13590 */
13591
Daniel Veillard4255d502002-04-16 15:50:10 +000013592 xmlSchemaInitTypes();
13593
Daniel Veillard6045c902002-10-09 21:13:59 +000013594 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013595 return (NULL);
13596
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013597 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013598 ctxt->counter = 0;
13599 ctxt->container = NULL;
13600
13601 /*
13602 * First step is to parse the input document into an DOM/Infoset
13603 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013604 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013605 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13606 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013607 if (doc == NULL) {
13608 xmlSchemaPErr(ctxt, NULL,
13609 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013610 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013611 ctxt->URL, NULL);
13612 return (NULL);
13613 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013614 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013615 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13616 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013617 if (doc == NULL) {
13618 xmlSchemaPErr(ctxt, NULL,
13619 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013620 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013621 NULL, NULL);
13622 return (NULL);
13623 }
13624 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013625 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013626 } else if (ctxt->doc != NULL) {
13627 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013628 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013629 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013630 xmlSchemaPErr(ctxt, NULL,
13631 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013632 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013633 NULL, NULL);
13634 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013635 }
13636
13637 /*
13638 * Then extract the root and Schema parse it
13639 */
13640 root = xmlDocGetRootElement(doc);
13641 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013642 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13643 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013644 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013645 if (!preserve) {
13646 xmlFreeDoc(doc);
13647 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013648 return (NULL);
13649 }
13650
13651 /*
13652 * Remove all the blank text nodes
13653 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013654 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013655
13656 /*
13657 * Then do the parsing for good
13658 */
13659 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013660 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013661 if (!preserve) {
13662 xmlFreeDoc(doc);
13663 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013664 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013665 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013666 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013667 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013668 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013669 ctxt->ctxtType = NULL;
13670 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013671 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013672 * Then fixup all attributes declarations
13673 */
13674 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13675
13676 /*
13677 * Then fixup all attributes group declarations
13678 */
13679 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13680 ctxt);
13681
13682 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013683 * Check attribute groups for circular references.
13684 */
13685 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13686 xmlSchemaCheckAttributeGroupCircular, ctxt);
13687
13688 /*
13689 * Then fixup all model group definitions.
13690 */
13691 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013692
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013693 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013694 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013695 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013696 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013697
13698 /*
13699 * Then fix references of element declaration; apply constraints.
13700 */
13701 xmlHashScanFull(ret->elemDecl,
13702 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013703
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013704 /*
13705 * Check model groups defnitions for circular references.
13706 */
13707 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13708 xmlSchemaCheckGroupDefCircular, ctxt);
13709
Daniel Veillard4255d502002-04-16 15:50:10 +000013710 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013711 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013712 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013713 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013714 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013715
13716 /*
13717 * Then check the defaults part of the type like facets values
13718 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013719 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000013720
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013721 /*
13722 * Validate the value constraint of attribute declarations/uses.
13723 */
13724 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13725
13726 /*
13727 * Validate the value constraint of element declarations.
13728 */
13729 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13730
Daniel Veillardc0826a72004-08-10 14:17:33 +000013731
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013732 if (ctxt->nberrors != 0) {
13733 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013734 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013735 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013736 return (ret);
13737}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013738
Daniel Veillard4255d502002-04-16 15:50:10 +000013739/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013740 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013741 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013742 * @err: the error callback
13743 * @warn: the warning callback
13744 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013745 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013746 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013747 */
13748void
13749xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013750 xmlSchemaValidityErrorFunc err,
13751 xmlSchemaValidityWarningFunc warn, void *ctx)
13752{
Daniel Veillard4255d502002-04-16 15:50:10 +000013753 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013754 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013755 ctxt->error = err;
13756 ctxt->warning = warn;
13757 ctxt->userData = ctx;
13758}
13759
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013760/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013761 * xmlSchemaGetParserErrors:
13762 * @ctxt: a XMl-Schema parser context
13763 * @err: the error callback result
13764 * @warn: the warning callback result
13765 * @ctx: contextual data for the callbacks result
13766 *
13767 * Get the callback information used to handle errors for a parser context
13768 *
13769 * Returns -1 in case of failure, 0 otherwise
13770 */
13771int
13772xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13773 xmlSchemaValidityErrorFunc * err,
13774 xmlSchemaValidityWarningFunc * warn, void **ctx)
13775{
13776 if (ctxt == NULL)
13777 return(-1);
13778 if (err != NULL)
13779 *err = ctxt->error;
13780 if (warn != NULL)
13781 *warn = ctxt->warning;
13782 if (ctx != NULL)
13783 *ctx = ctxt->userData;
13784 return(0);
13785}
13786
13787/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013788 * xmlSchemaFacetTypeToString:
13789 * @type: the facet type
13790 *
13791 * Convert the xmlSchemaTypeType to a char string.
13792 *
13793 * Returns the char string representation of the facet type if the
13794 * type is a facet and an "Internal Error" string otherwise.
13795 */
13796static const char *
13797xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13798{
13799 switch (type) {
13800 case XML_SCHEMA_FACET_PATTERN:
13801 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013802 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013803 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013804 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013805 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013806 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013807 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013808 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013809 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013810 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013811 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013812 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013813 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013814 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013815 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013816 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013817 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013818 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013819 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013820 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013821 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013822 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013823 return ("fractionDigits");
13824 default:
13825 break;
13826 }
13827 return ("Internal Error");
13828}
13829
Daniel Veillardc0826a72004-08-10 14:17:33 +000013830
Daniel Veillardc0826a72004-08-10 14:17:33 +000013831
13832static int
13833xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13834{
13835 xmlSchemaTypePtr anc;
13836
13837 /*
13838 * The normalization type can be changed only for types which are derived
13839 * from xsd:string.
13840 */
13841 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013842 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013843 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013844 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
13845 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013846 else {
13847 /*
13848 * For all ·atomic· datatypes other than string (and types ·derived·
13849 * by ·restriction· from it) the value of whiteSpace is fixed to
13850 * collapse
13851 */
13852 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13853 }
13854 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13855 /*
13856 * For list types the facet "whiteSpace" is fixed to "collapse".
13857 */
13858 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13859 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13860 return (-1);
13861 } else if (type->facetSet != NULL) {
13862 xmlSchemaTypePtr anyST;
13863 xmlSchemaFacetLinkPtr lin;
13864
13865 /*
13866 * Atomic types.
13867 */
13868 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13869 anc = type->baseType;
13870 do {
13871 /*
13872 * For all ·atomic· datatypes other than string (and types ·derived·
13873 * by ·restriction· from it) the value of whiteSpace is fixed to
13874 * collapse
13875 */
13876 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13877 (anc->builtInType == XML_SCHEMAS_STRING)) {
13878
13879 lin = type->facetSet;
13880 do {
13881 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13882 if (lin->facet->whitespace ==
13883 XML_SCHEMAS_FACET_COLLAPSE) {
13884 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13885 } else if (lin->facet->whitespace ==
13886 XML_SCHEMAS_FACET_REPLACE) {
13887 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13888 } else
13889 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13890 break;
13891 }
13892 lin = lin->next;
13893 } while (lin != NULL);
13894 break;
13895 }
13896 anc = anc->baseType;
13897 } while (anc != anyST);
13898 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13899 }
13900 return (-1);
13901}
13902
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013903/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013904 * xmlSchemaValidateFacetsInternal:
13905 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013906 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013907 * @facets: the list of facets to check
13908 * @value: the lexical repr of the value to validate
13909 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013910 * @fireErrors: if 0, only internal errors will be fired;
13911 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013912 *
13913 * Check a value against all facet conditions
13914 *
13915 * Returns 0 if the element is schemas valid, a positive error code
13916 * number otherwise and -1 in case of internal or API error.
13917 */
13918static int
13919xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013920 xmlSchemaTypePtr type,
13921 const xmlChar * value,
13922 unsigned long length,
13923 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013924{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013925 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013926 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013927 xmlSchemaTypePtr biType; /* The build-in type. */
13928 xmlSchemaTypePtr tmpType;
13929 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013930 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013931 xmlSchemaFacetPtr facet;
13932 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013933
Daniel Veillardc0826a72004-08-10 14:17:33 +000013934#ifdef DEBUG_UNION_VALIDATION
13935 printf("Facets of type: '%s'\n", (const char *) type->name);
13936 printf(" fireErrors: %d\n", fireErrors);
13937#endif
13938
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013939 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013940 /*
13941 * NOTE: Do not jump away, if the facetSet of the given type is
13942 * empty: until now, "pattern" facets of the *base types* need to
13943 * be checked as well.
13944 */
13945 biType = type->baseType;
13946 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13947 biType = biType->baseType;
13948 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013949 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013950 "Internal error: xmlSchemaValidateFacetsInternal, "
13951 "the base type axis of the given type '%s' does not resolve to "
13952 "a built-in type.\n",
13953 type->name, NULL);
13954 return (-1);
13955 }
13956
13957 if (type->facetSet != NULL) {
13958 facetLink = type->facetSet;
13959 while (facetLink != NULL) {
13960 facet = facetLink->facet;
13961 /*
13962 * Skip the pattern "whiteSpace": it is used to
13963 * format the character content beforehand.
13964 */
13965 switch (facet->type) {
13966 case XML_SCHEMA_FACET_WHITESPACE:
13967 case XML_SCHEMA_FACET_PATTERN:
13968 case XML_SCHEMA_FACET_ENUMERATION:
13969 break;
13970 case XML_SCHEMA_FACET_LENGTH:
13971 case XML_SCHEMA_FACET_MINLENGTH:
13972 case XML_SCHEMA_FACET_MAXLENGTH:
13973 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13974 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13975 value, length, 0);
13976 len = length;
13977 } else
13978 ret = xmlSchemaValidateLengthFacet(biType, facet,
13979 value, ctxt->value, &len);
13980 break;
13981 default:
13982 ret = xmlSchemaValidateFacet(biType, facet, value,
13983 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013984 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013985 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013986 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013987 "Internal error: xmlSchemaValidateFacetsInternal, "
13988 "validating facet of type '%s'.\n",
13989 type->name, NULL);
13990 break;
13991 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013992 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013993 type, facet, NULL, NULL, NULL, NULL);
13994 }
13995
13996 facetLink = facetLink->next;
13997 }
13998 if (ret >= 0) {
13999 /*
14000 * Process enumerations.
14001 */
14002 retFacet = 0;
14003 facetLink = type->facetSet;
14004 while (facetLink != NULL) {
14005 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14006 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14007 value, ctxt->value);
14008 if (retFacet <= 0)
14009 break;
14010 }
14011 facetLink = facetLink->next;
14012 }
14013 if (retFacet > 0) {
14014 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14015 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014016 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014017 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14018 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014019 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014020 "Internal error: xmlSchemaValidateFacetsInternal, "
14021 "validating facet of type '%s'.\n",
14022 BAD_CAST "enumeration", NULL);
14023 ret = -1;
14024 }
14025 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014026 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014027 if (ret >= 0) {
14028 /*
14029 * Process patters. Pattern facets are ORed at type level
14030 * and ANDed if derived. Walk the base type axis.
14031 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014032 tmpType = type;
14033 facet = NULL;
14034 do {
14035 retFacet = 0;
14036 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014037 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014038 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14039 continue;
14040 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14041 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014042 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014043 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014044 else if (retFacet < 0) {
14045 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14046 "Internal error: xmlSchemaValidateFacetsInternal, "
14047 "validating 'pattern' facet '%s' of type '%s'.\n",
14048 facetLink->facet->value, tmpType->name);
14049 ret = -1;
14050 break;
14051 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014052 /* Save the last non-validating facet. */
14053 facet = facetLink->facet;
14054 }
14055 if (retFacet != 0)
14056 break;
14057 tmpType = tmpType->baseType;
14058 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014059 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014060 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14061 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014062 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014063 NULL, NULL, NULL, NULL);
14064 }
14065 }
14066 }
14067
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014068 return (ret);
14069}
14070
Daniel Veillard4255d502002-04-16 15:50:10 +000014071/************************************************************************
14072 * *
14073 * Simple type validation *
14074 * *
14075 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000014076
Daniel Veillard4255d502002-04-16 15:50:10 +000014077
14078/************************************************************************
14079 * *
14080 * DOM Validation code *
14081 * *
14082 ************************************************************************/
14083
Daniel Veillard4255d502002-04-16 15:50:10 +000014084static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014085 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000014086 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014087static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014088 xmlSchemaTypePtr type,
14089 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000014090
Daniel Veillard3646d642004-06-02 19:19:14 +000014091
14092/**
14093 * xmlSchemaFreeAttrStates:
14094 * @state: a list of attribute states
14095 *
14096 * Free the given list of attribute states
14097 *
14098 */
14099static void
14100xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
14101{
14102 xmlSchemaAttrStatePtr tmp;
14103 while (state != NULL) {
14104 tmp = state;
14105 state = state->next;
14106 xmlFree(tmp);
14107 }
14108}
14109
Daniel Veillard4255d502002-04-16 15:50:10 +000014110/**
14111 * xmlSchemaRegisterAttributes:
14112 * @ctxt: a schema validation context
14113 * @attrs: a list of attributes
14114 *
14115 * Register the list of attributes as the set to be validated on that element
14116 *
14117 * Returns -1 in case of error, 0 otherwise
14118 */
14119static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014120xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
14121{
Daniel Veillard3646d642004-06-02 19:19:14 +000014122 xmlSchemaAttrStatePtr tmp;
14123
14124 ctxt->attr = NULL;
14125 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014126 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014127 if ((attrs->ns != NULL) &&
14128 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
14129 attrs = attrs->next;
14130 continue;
14131 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014132 tmp = (xmlSchemaAttrStatePtr)
14133 xmlMalloc(sizeof(xmlSchemaAttrState));
14134 if (tmp == NULL) {
14135 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
14136 return (-1);
14137 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014138 tmp->attr = attrs;
14139 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
14140 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014141 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014142 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014143 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000014144 else
14145 ctxt->attrTop->next = tmp;
14146 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014147 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014148 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014149 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014150}
14151
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014152#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000014153/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014154 * xmlSchemaValidateCheckNodeList
14155 * @nodelist: the list of nodes
14156 *
14157 * Check the node list is only made of text nodes and entities pointing
14158 * to text nodes
14159 *
14160 * Returns 1 if true, 0 if false and -1 in case of error
14161 */
14162static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014163xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
14164{
Daniel Veillard4255d502002-04-16 15:50:10 +000014165 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014166 if (nodelist->type == XML_ENTITY_REF_NODE) {
14167 TODO /* implement recursion in the entity content */
14168 }
14169 if ((nodelist->type != XML_TEXT_NODE) &&
14170 (nodelist->type != XML_COMMENT_NODE) &&
14171 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000014172 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014173 return (0);
14174 }
14175 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014176 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014177 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014178}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014179#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014180
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014181static void
14182xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14183{
14184 int i, nbItems;
14185 xmlSchemaTypePtr item, *items;
14186
14187
14188 /*
14189 * During the Assemble of the schema ctxt->curItems has
14190 * been filled with the relevant new items. Fix those up.
14191 */
14192 nbItems = ctxt->assemble->nbItems;
14193 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14194
14195 for (i = 0; i < nbItems; i++) {
14196 item = items[i];
14197 switch (item->type) {
14198 case XML_SCHEMA_TYPE_ATTRIBUTE:
14199 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14200 break;
14201 case XML_SCHEMA_TYPE_ELEMENT:
14202 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14203 NULL, NULL, NULL);
14204 break;
14205 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14206 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14207 ctxt, NULL);
14208 break;
14209 case XML_SCHEMA_TYPE_GROUP:
14210 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14211 default:
14212 break;
14213 }
14214 }
14215 /*
14216 * Circularity checks.
14217 */
14218 for (i = 0; i < nbItems; i++) {
14219 item = items[i];
14220 switch (item->type) {
14221 case XML_SCHEMA_TYPE_GROUP:
14222 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14223 break;
14224 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14225 xmlSchemaCheckAttributeGroupCircular(
14226 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14227 break;
14228 default:
14229 break;
14230 }
14231 }
14232 /*
14233 * Fixup for all other item.
14234 * TODO: Hmm, not sure if starting from complex/simple types,
14235 * all subsequent items will be reached.
14236 */
14237 for (i = 0; i < nbItems; i++) {
14238 item = items[i];
14239 switch (item->type) {
14240 case XML_SCHEMA_TYPE_SIMPLE:
14241 case XML_SCHEMA_TYPE_COMPLEX:
14242 xmlSchemaTypeFixup(item, ctxt, NULL);
14243 break;
14244 default:
14245 break;
14246 }
14247 }
14248 /*
14249 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014250 * hold by simple type components only (and
14251 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014252 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014253 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014254 for (i = 0; i < nbItems; i++) {
14255 item = items[i];
14256 switch (item->type) {
14257 case XML_SCHEMA_TYPE_SIMPLE:
14258 case XML_SCHEMA_TYPE_COMPLEX:
14259 xmlSchemaCheckDefaults(item, ctxt, NULL);
14260 break;
14261 default:
14262 break;
14263 }
14264 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014265 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014266 /*
14267 * Build the content model for complex types.
14268 */
14269 for (i = 0; i < nbItems; i++) {
14270 item = items[i];
14271 switch (item->type) {
14272 case XML_SCHEMA_TYPE_COMPLEX:
14273 xmlSchemaBuildContentModel(item, ctxt, NULL);
14274 break;
14275 default:
14276 break;
14277 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014278 }
14279 /*
14280 * Validate value contraint values.
14281 */
14282 for (i = 0; i < nbItems; i++) {
14283 item = items[i];
14284 switch (item->type) {
14285 case XML_SCHEMA_TYPE_ATTRIBUTE:
14286 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14287 break;
14288 case XML_SCHEMA_TYPE_ELEMENT:
14289 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14290 break;
14291 default:
14292 break;
14293 }
14294 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014295}
14296
14297/**
14298 * xmlSchemaAssembleByLocation:
14299 * @pctxt: a schema parser context
14300 * @vctxt: a schema validation context
14301 * @schema: the existing schema
14302 * @node: the node that fired the assembling
14303 * @nsName: the namespace name of the new schema
14304 * @location: the location of the schema
14305 *
14306 * Expands an existing schema by an additional schema.
14307 *
14308 * Returns 0 if the new schema is correct, a positive error code
14309 * number otherwise and -1 in case of an internal or API error.
14310 */
14311static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014312xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14313 xmlSchemaPtr schema,
14314 xmlNodePtr node,
14315 const xmlChar *nsName,
14316 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014317{
14318 const xmlChar *targetNs, *oldtns;
14319 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014320 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014321 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014322 xmlSchemaParserCtxtPtr pctxt;
14323
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014324 /*
14325 * This should be used:
14326 * 1. on <import>(s)
14327 * 2. if requested by the validated instance
14328 * 3. if requested via the API
14329 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014330 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014331 return (-1);
14332 /*
14333 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014334 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014335 if ((vctxt->pctxt == NULL) &&
14336 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14337 xmlSchemaVErr(vctxt, node,
14338 XML_SCHEMAV_INTERNAL,
14339 "Internal error: xmlSchemaAssembleByLocation, "
14340 "failed to create a temp. parser context.\n",
14341 NULL, NULL);
14342 return (-1);
14343 }
14344 pctxt = vctxt->pctxt;
14345 /*
14346 * Set the counter to produce unique names for anonymous items.
14347 */
14348 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014349 /*
14350 * Acquire the schema document.
14351 */
14352 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14353 nsName, location, &doc, &targetNs, 0);
14354 if (ret != 0) {
14355 if (doc != NULL)
14356 xmlFreeDoc(doc);
14357 } else if (doc != NULL) {
14358 docElem = xmlDocGetRootElement(doc);
14359 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014360 * Create new assemble info.
14361 */
14362 if (pctxt->assemble == NULL) {
14363 pctxt->assemble = xmlSchemaNewAssemble();
14364 if (pctxt->assemble == NULL) {
14365 xmlSchemaVErrMemory(vctxt,
14366 "Memory error: xmlSchemaAssembleByLocation, "
14367 "allocating assemble info", NULL);
14368 xmlFreeDoc(doc);
14369 return (-1);
14370 }
14371 }
14372 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014373 * Save and reset the context & schema.
14374 */
14375 oldflags = schema->flags;
14376 oldtns = schema->targetNamespace;
14377 olddoc = schema->doc;
14378
14379 xmlSchemaClearSchemaDefaults(schema);
14380 schema->targetNamespace = targetNs;
14381 /* schema->nbCurItems = 0; */
14382 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014383 pctxt->ctxtType = NULL;
14384 pctxt->parentItem = NULL;
14385
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014386 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14387 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014388 xmlSchemaPostSchemaAssembleFixup(pctxt);
14389 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014390 * Set the counter of items.
14391 */
14392 schema->counter = pctxt->counter;
14393 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014394 * Free the list of assembled components.
14395 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014396 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014397 /*
14398 * Restore the context & schema.
14399 */
14400 schema->flags = oldflags;
14401 schema->targetNamespace = oldtns;
14402 schema->doc = olddoc;
14403 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014404 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014405 return (ret);
14406}
14407
14408/**
14409 * xmlSchemaAssembleByXSIAttr:
14410 * @vctxt: a schema validation context
14411 * @xsiAttr: an xsi attribute
14412 * @noNamespace: whether a schema with no target namespace is exptected
14413 *
14414 * Expands an existing schema by an additional schema using
14415 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14416 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14417 * must be set to 1.
14418 *
14419 * Returns 0 if the new schema is correct, a positive error code
14420 * number otherwise and -1 in case of an internal or API error.
14421 */
14422static int
14423xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14424 xmlAttrPtr xsiAttr,
14425 int noNamespace)
14426{
14427 xmlChar *value;
14428 const xmlChar *cur, *end;
14429 const xmlChar *nsname = NULL, *location;
14430 int count = 0;
14431 int ret = 0;
14432
14433 if (xsiAttr == NULL) {
14434 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14435 NULL, NULL,
14436 "Internal error: xmlSchemaAssembleByXSIAttr, "
14437 "bad arguments", NULL);
14438 return (-1);
14439 }
14440 /*
14441 * Parse the value; we will assume an even number of values
14442 * to be given (this is how Xerces and XSV work).
14443 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014444 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014445 cur = value;
14446 do {
14447 if (noNamespace != 1) {
14448 /*
14449 * Get the namespace name.
14450 */
14451 while (IS_BLANK_CH(*cur))
14452 cur++;
14453 end = cur;
14454 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14455 end++;
14456 if (end == cur)
14457 break;
14458 count++;
14459 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14460 cur = end;
14461 }
14462 /*
14463 * Get the URI.
14464 */
14465 while (IS_BLANK_CH(*cur))
14466 cur++;
14467 end = cur;
14468 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14469 end++;
14470 if (end == cur)
14471 break;
14472 count++;
14473 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014474 cur = end;
14475 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014476 xsiAttr->parent, nsname, location);
14477 if (ret == -1) {
14478 xmlSchemaVCustomErr(vctxt,
14479 XML_SCHEMAV_INTERNAL,
14480 (xmlNodePtr) xsiAttr, NULL,
14481 "Internal error: xmlSchemaAssembleByXSIAttr, "
14482 "assembling schemata", NULL);
14483 if (value != NULL)
14484 xmlFree(value);
14485 return (-1);
14486 }
14487 } while (*cur != 0);
14488 if (value != NULL)
14489 xmlFree(value);
14490 return (ret);
14491}
14492
14493/**
14494 * xmlSchemaAssembleByXSIElem:
14495 * @vctxt: a schema validation context
14496 * @elem: an element node possibly holding xsi attributes
14497 * @noNamespace: whether a schema with no target namespace is exptected
14498 *
14499 * Assembles an existing schema by an additional schema using
14500 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14501 * of the given @elem.
14502 *
14503 * Returns 0 if the new schema is correct, a positive error code
14504 * number otherwise and -1 in case of an internal or API error.
14505 */
14506static int
14507xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14508 xmlNodePtr elem)
14509{
14510 int ret = 0, retNs = 0;
14511 xmlAttrPtr attr;
14512
14513 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14514 if (attr != NULL) {
14515 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14516 if (retNs == -1)
14517 return (-1);
14518 }
14519 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14520 if (attr != NULL) {
14521 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14522 if (ret == -1)
14523 return (-1);
14524 }
14525 if (retNs != 0)
14526 return (retNs);
14527 else
14528 return (ret);
14529}
14530
Daniel Veillard4255d502002-04-16 15:50:10 +000014531/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014532 * xmlSchemaValidateCallback:
14533 * @ctxt: a schema validation context
14534 * @name: the name of the element detected (might be NULL)
14535 * @type: the type
14536 *
14537 * A transition has been made in the automata associated to an element
14538 * content model
14539 */
14540static void
14541xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014542 const xmlChar * name ATTRIBUTE_UNUSED,
14543 xmlSchemaTypePtr type, xmlNodePtr node)
14544{
Daniel Veillard4255d502002-04-16 15:50:10 +000014545 xmlSchemaTypePtr oldtype = ctxt->type;
14546 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014547
Daniel Veillard4255d502002-04-16 15:50:10 +000014548#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014549 xmlGenericError(xmlGenericErrorContext,
14550 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014551 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014552#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014553 /*
14554 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14555 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014556 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014557 ctxt->node = node;
14558 ctxt->cur = node->children;
14559 /*
14560 * Assemble new schemata using xsi.
14561 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014562 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014563 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014564
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014565 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14566 if (ret == -1) {
14567 xmlSchemaVCustomErr(ctxt,
14568 XML_SCHEMAV_INTERNAL,
14569 ctxt->node, NULL,
14570 "Internal error: xmlSchemaValidateElement, "
14571 "assembling schema by xsi", NULL);
14572 return;
14573 }
14574 /*
14575 * NOTE: We won't react on schema parser errors here.
14576 * TODO: But a warning would be nice.
14577 */
14578 }
14579 switch (type->type) {
14580 case XML_SCHEMA_TYPE_ELEMENT: {
14581 /*
14582 * NOTE: The build of the content model
14583 * (xmlSchemaBuildAContentModel) ensures that the element
14584 * declaration (and not a reference to it) will be given.
14585 */
14586 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14587 /*
14588 * This is paranoid coding ;-)... it should not
14589 * happen here any more.
14590 */
14591 xmlSchemaVCustomErr(ctxt,
14592 XML_SCHEMAV_INTERNAL,
14593 node, NULL,
14594 "Internal error: xmlSchemaValidateCallback, "
14595 "element declaration 'reference' encountered, "
14596 "but an element declaration was expected",
14597 NULL);
14598 return;
14599 }
14600 xmlSchemaValidateElementByDeclaration(ctxt,
14601 (xmlSchemaElementPtr) type);
14602 break;
14603 }
14604 case XML_SCHEMA_TYPE_ANY:
14605 xmlSchemaValidateElementByWildcard(ctxt, type);
14606 break;
14607 default:
14608 break;
14609 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014610 ctxt->type = oldtype;
14611 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014612}
Daniel Veillard4255d502002-04-16 15:50:10 +000014613
Daniel Veillard01fa6152004-06-29 17:04:39 +000014614/**
14615 * xmlSchemaValidateSimpleTypeValue:
14616 * @ctxt: a schema validation context
14617 * @value: the value to be validated
14618 * @fireErrors: shall errors be reported?
14619 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014620 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014621 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014622 *
14623 * Validates a value by the given type (user derived or built-in).
14624 *
14625 * Returns 0 if the value is valid, a positive error code
14626 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014627 */
14628static int
14629xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014630 xmlSchemaTypePtr type,
14631 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014632 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014633 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014634 int normalize,
14635 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014636{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014637 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014638 int ret = 0;
14639 xmlChar *normValue = NULL;
14640 int wtsp;
14641
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014642 node = ctxt->node;
14643 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014644 wtsp = ctxt->valueWS;
14645 /*
14646 * Normalize the value.
14647 */
14648 if (normalize &&
14649 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14650 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14651
14652 if ((norm != -1) && (norm > ctxt->valueWS)) {
14653 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14654 normValue = xmlSchemaCollapseString(value);
14655 else
14656 normValue = xmlSchemaWhiteSpaceReplace(value);
14657 ctxt->valueWS = norm;
14658 if (normValue != NULL)
14659 value = (const xmlChar *) normValue;
14660 }
14661 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014662 /*
14663 * The nodes of a content must be checked only once,
14664 * this is not working since list types will fire this
14665 * multiple times.
14666 */
14667 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14668 xmlNodePtr cur = ctxt->cur;
14669
14670 do {
14671 switch (cur->type) {
14672 case XML_TEXT_NODE:
14673 case XML_CDATA_SECTION_NODE:
14674 case XML_PI_NODE:
14675 case XML_COMMENT_NODE:
14676 case XML_XINCLUDE_START:
14677 case XML_XINCLUDE_END:
14678 break;
14679 case XML_ENTITY_REF_NODE:
14680 case XML_ENTITY_NODE:
14681 /* TODO: Scour the entities for illegal nodes. */
14682 TODO break;
14683 case XML_ELEMENT_NODE: {
14684 /* NOTE: Changed to an internal error, since the
14685 * existence of an element node will be already checked in
14686 * xmlSchemaValidateElementBySimpleType and in
14687 * xmlSchemaValidateElementByComplexType.
14688 */
14689 xmlSchemaVCustomErr(ctxt,
14690 XML_SCHEMAV_INTERNAL,
14691 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14692 node, type,
14693 "Element '%s' found in simple type content",
14694 cur->name);
14695 return (XML_SCHEMAV_INTERNAL);
14696 }
14697 case XML_ATTRIBUTE_NODE:
14698 case XML_DOCUMENT_NODE:
14699 case XML_DOCUMENT_TYPE_NODE:
14700 case XML_DOCUMENT_FRAG_NODE:
14701 case XML_NOTATION_NODE:
14702 case XML_HTML_DOCUMENT_NODE:
14703 case XML_DTD_NODE:
14704 case XML_ELEMENT_DECL:
14705 case XML_ATTRIBUTE_DECL:
14706 case XML_ENTITY_DECL:
14707 case XML_NAMESPACE_DECL:
14708#ifdef LIBXML_DOCB_ENABLED
14709 case XML_DOCB_DOCUMENT_NODE:
14710#endif
14711 xmlSchemaVCustomErr(ctxt,
14712 XML_SCHEMAV_INTERNAL,
14713 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14714 node, NULL,
14715 "Node of unexpected type found in simple type content",
14716 NULL);
14717 return (XML_SCHEMAV_INTERNAL);
14718 }
14719 cur = cur->next;
14720 } while (cur != NULL);
14721 }
14722
William M. Brack2f2a6632004-08-20 23:09:47 +000014723 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14724 xmlSchemaTypePtr base, anyType;
14725
14726 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14727
14728 base = type->baseType;
14729 while ((base != NULL) &&
14730 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14731 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14732 (base != anyType)) {
14733 base = base->baseType;
14734 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014735 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014736 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014737 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014738 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14739 "validating complex type '%s'\n",
14740 type->name, NULL);
14741 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14742 /*
14743 * Check facets.
14744 */
14745 /*
14746 * This is somehow not nice, since if an error occurs
14747 * the reported type will be the complex type; the spec
14748 * wants a simple type to be created on the complex type
14749 * if it has a simple content. For now we have to live with
14750 * it.
14751 */
14752 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14753 value, 0, fireErrors);
14754 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014755 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014756 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14757 "validating facets of complex type '%s'\n",
14758 type->name, NULL);
14759 } else if (ret > 0) {
14760 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014761 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014762 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014763 }
14764 }
14765 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014766
14767 if (ctxt->value != NULL) {
14768 xmlSchemaFreeValue(ctxt->value);
14769 ctxt->value = NULL;
14770 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014771 /*
14772 * STREAM-READ-CHILDREN.
14773 */
14774 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014775 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014776 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14777 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14778 else
14779 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014780 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014781 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014782 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014783 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014784 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014785 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014786 }
14787 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14788 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14789 * a literal in the ·lexical space· of {base type definition}
14790 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014791 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014792 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014793 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014794 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014795 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014796 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014797 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014798 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014799 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014800 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014801 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014802 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014803 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014804 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014805 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14806 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014807 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014808 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014809 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014810 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014811 type->name, NULL);
14812 } else if (ret > 0) {
14813 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014814 /*
14815 Disabled, since the facet validation already reports errors.
14816 if (fireErrors)
14817 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14818 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014819 }
14820 }
14821 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14822
14823 xmlSchemaTypePtr tmpType;
14824 const xmlChar *cur, *end;
14825 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014826 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014827
14828 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14829 * of white space separated tokens, each of which ·match·es a literal
14830 * in the ·lexical space· of {item type definition}
14831 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000014832
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000014833 if (value == NULL)
14834 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000014835 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014836 cur = value;
14837 do {
14838 while (IS_BLANK_CH(*cur))
14839 cur++;
14840 end = cur;
14841 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14842 end++;
14843 if (end == cur)
14844 break;
14845 tmp = xmlStrndup(cur, end - cur);
14846 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014847 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014848 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014849 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014850 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014851 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14852 "validating an item of list simple type '%s'\n",
14853 type->name, NULL);
14854 break;
14855 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014856 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014857 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014858 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014859 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014860 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014861 cur = end;
14862 } while (*cur != 0);
14863 /*
14864 * Check facets.
14865 */
14866 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014867 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014868 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014869 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014870 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014871 } else if ((ret == 0) && (applyFacets)) {
14872 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14873 value, len, fireErrors);
14874 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014875 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014876 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14877 "validating facets of list simple type '%s'\n",
14878 type->name, NULL);
14879 } else if (ret > 0) {
14880 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014881 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014882 Disabled, since the facet validation already reports errors.
14883 if (fireErrors)
14884 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014885 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014886 }
14887
Daniel Veillard01fa6152004-06-29 17:04:39 +000014888 }
14889 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14890 xmlSchemaTypeLinkPtr memberLink;
14891
14892 /*
14893 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14894 * not apply directly; however, the normalization behavior of ·union·
14895 * types is controlled by the value of whiteSpace on that one of the
14896 * ·memberTypes· against which the ·union· is successfully validated.
14897 *
14898 * This means that the value is normalized by the first validating
14899 * member type, then the facets of the union type are applied. This
14900 * needs changing of the value!
14901 */
14902
14903 /*
14904 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14905 * literal in the ·lexical space· of at least one member of
14906 * {member type definitions}
14907 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014908#ifdef DEBUG_UNION_VALIDATION
14909 printf("Union ST : '%s'\n", (const char *) type->name);
14910 printf(" fireErrors : %d\n", fireErrors);
14911 printf(" applyFacets: %d\n", applyFacets);
14912#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014913 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14914 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014915 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014916 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014917 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014918 type->name, NULL);
14919 ret = -1;
14920 }
14921 if (ret == 0) {
14922 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014923 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14924 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014925 if ((ret <= 0) || (ret == 0))
14926 break;
14927 memberLink = memberLink->next;
14928 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014929 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014930 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014931 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014932 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014933 type->name, NULL);
14934 } else if (ret > 0) {
14935 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014936 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014937 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014938 }
14939 }
14940 /*
14941 * Apply facets (pattern, enumeration).
14942 */
14943 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14944 int mws;
14945 /*
14946 * The normalization behavior of ·union· types is controlled by
14947 * the value of whiteSpace on that one of the ·memberTypes·
14948 * against which the ·union· is successfully validated.
14949 */
14950 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014951 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014952 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14953 "the value was already normalized for the union simple "
14954 "type '%s'.\n", type->name, NULL);
14955 }
14956 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14957 if (mws > ctxt->valueWS) {
14958 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14959 normValue = xmlSchemaCollapseString(value);
14960 else
14961 normValue = xmlSchemaWhiteSpaceReplace(value);
14962 if (normValue != NULL)
14963 value = (const xmlChar *) normValue;
14964 }
14965
14966 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14967 value, 0, fireErrors);
14968 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014969 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014970 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14971 "validating facets of union simple type '%s'\n",
14972 type->name, NULL);
14973 } else if (ret > 0) {
14974 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14975 /*
14976 if (fireErrors)
14977 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14978 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014979 }
14980 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014981 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014982 ctxt->valueWS = wtsp;
14983 if (normValue != NULL)
14984 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014985 return (ret);
14986}
14987
14988/**
14989 * xmlSchemaValidateSimpleTypeElement:
14990 * @ctxt: a schema validation context
14991 * @node: the element node to be validated.
14992 *
14993 * Validate the element against a simple type.
14994 *
14995 * Returns 0 if the element is valid, a positive error code
14996 * number otherwise and -1 in case of an internal or API error.
14997 */
14998static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014999xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015000 xmlSchemaTypePtr type,
15001 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015002{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015003 xmlSchemaTypePtr oldtype;
15004 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015005 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015006 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015007 int ret = 0, retval = 0;
15008
Daniel Veillard01fa6152004-06-29 17:04:39 +000015009 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015010 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
15011 "Internal error: xmlSchemaValidateElementBySimpleType, "
15012 "bad arguments", NULL);
15013 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015014 }
15015
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015016 oldtype = ctxt->type;
15017 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015018 /*
15019 * cvc-type: 3.1.2 The element information item must have no element
15020 * information item [children].
15021 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015022 /*
15023 * STREAM: Child nodes are processed.
15024 */
15025 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015026 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015027 /*
15028 * TODO: Entities, will they produce elements as well?
15029 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015030 if (cur->type == XML_ELEMENT_NODE) {
15031 xmlSchemaVCustomErr(ctxt,
15032 XML_SCHEMAV_CVC_TYPE_3_1_2,
15033 node, type,
15034 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015035 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015036 }
15037 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015038 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015039
Daniel Veillard01fa6152004-06-29 17:04:39 +000015040 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015041 * cvc-type 3.1.1:
15042 *
15043 * The attributes of must be empty, excepting those whose namespace name
15044 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
15045 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015046 */
15047 /*
15048 * STREAM: Attribute nodes are processed.
15049 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015050 attr = node->properties;
15051 while (attr != NULL) {
15052 if ((attr->ns == NULL) ||
15053 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
15054 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
15055 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
15056 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
15057 (!xmlStrEqual
15058 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015059 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015060 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
15061 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015062 }
15063 attr = attr->next;
15064 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015065 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015066 * This will skip validation if the type is 'anySimpleType' and
15067 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015068 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015069 if ((valSimpleContent == 1) &&
15070 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
15071 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015072 xmlChar *value;
15073
15074 value = xmlNodeGetContent(node);
15075 /*
15076 * NOTE: This call will not check the content nodes, since
15077 * this should be checked here already.
15078 */
15079 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
15080 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015081 if (value != NULL)
15082 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015083 if (retval != 0)
15084 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000015085 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015086 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015087 return (ret);
15088}
Daniel Veillard4255d502002-04-16 15:50:10 +000015089
15090/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015091 * xmlSchemaValQNameAcquire:
15092 * @value: the lexical represantation of the QName value
15093 * @node: the node to search for the corresponding namespace declaration
15094 * @nsName: the resulting namespace name if found
15095 *
15096 * Checks that a value conforms to the lexical space of the type QName;
15097 * if valid, the corresponding namespace name is searched and retured
15098 * as a copy in @nsName. The local name is returned in @localName as
15099 * a copy.
15100 *
15101 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
15102 * namespace declaration was found in scope; -1 in case of an internal or
15103 * API error.
15104 */
15105static int
15106xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
15107 xmlChar **nsName, xmlChar **localName)
15108{
15109 int ret;
15110 xmlChar *local = NULL;
15111
15112 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
15113 return (-1);
15114 *nsName = NULL;
15115 *localName = NULL;
15116 ret = xmlValidateQName(value, 1);
15117 if (ret == 0) {
15118 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015119 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015120
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015121 /*
15122 * NOTE: xmlSplitQName2 will return a duplicated
15123 * string.
15124 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015125 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015126 if (local == NULL)
15127 local = xmlStrdup(value);
15128 ns = xmlSearchNs(node->doc, node, prefix);
15129 /*
15130 * A namespace need not to be found if the prefix is NULL.
15131 */
15132 if (ns != NULL) {
15133 /*
15134 * TODO: Is it necessary to duplicate the URI here?
15135 */
15136 *nsName = xmlStrdup(ns->href);
15137 } else if (prefix != NULL) {
15138 xmlFree(prefix);
15139 if (local != NULL)
15140 xmlFree(local);
15141 return (2);
15142 }
15143 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015144 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015145 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015146 } else
15147 return (1);
15148 return (ret);
15149}
15150
15151/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015152 * xmlSchemaHasElemContent:
15153 * @node: the node
15154 *
15155 * Scours the content of the given node for element
15156 * nodes.
15157 *
15158 * Returns 1 if an element node is found,
15159 * 0 otherwise.
15160 */
15161static int
15162xmlSchemaHasElemContent(xmlNodePtr node)
15163{
15164 if (node == NULL)
15165 return (0);
15166 node = node->children;
15167 while (node != NULL) {
15168 if (node->type == XML_ELEMENT_NODE)
15169 return (1);
15170 node = node->next;
15171 }
15172 return (0);
15173}
15174/**
15175 * xmlSchemaHasElemOrCharContent:
15176 * @node: the node
15177 *
15178 * Scours the content of the given node for element
15179 * and character nodes.
15180 *
15181 * Returns 1 if an element or character node is found,
15182 * 0 otherwise.
15183 */
15184static int
15185xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15186{
15187 if (node == NULL)
15188 return (0);
15189 node = node->children;
15190 while (node != NULL) {
15191 switch (node->type) {
15192 case XML_ELEMENT_NODE:
15193 /*
15194 * TODO: Ask Daniel if these are all character nodes.
15195 */
15196 case XML_TEXT_NODE:
15197 case XML_CDATA_SECTION_NODE:
15198 /*
15199 * TODO: How XML_ENTITY_NODEs evaluated?
15200 */
15201 case XML_ENTITY_REF_NODE:
15202 case XML_ENTITY_NODE:
15203 return (1);
15204 break;
15205 default:
15206 break;
15207 }
15208 node = node->next;
15209 }
15210 return (0);
15211}
15212
15213
15214/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015215 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015216 * @ctxt: a schema validation context
15217 * @node: the top node.
15218 *
15219 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015220 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015221 *
15222 * Returns 0 if the element is schemas valid, a positive error code
15223 * number otherwise and -1 in case of internal or API error.
15224 */
15225static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015226xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15227 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015228{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015229 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015230 int ret = 0;
15231 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015232 xmlAttrPtr attr;
15233 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015234 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015235
15236 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015237 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15238 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015239 * Note that @elemDecl will be the declaration and never the
15240 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015241 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015242
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015243 if (ctxt == NULL) {
15244 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15245 "Internal error: xmlSchemaValidateElementByDeclaration, "
15246 "bad arguments.\n",
15247 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015248 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015249 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015250
15251 elem = ctxt->node;
15252
15253 /*
15254 * cvc-elt (3.3.4) : 1
15255 */
15256 if (elemDecl == NULL) {
15257 xmlSchemaVCustomErr(ctxt,
15258 XML_SCHEMAV_CVC_ELT_1,
15259 elem, NULL,
15260 "No matching declaration available", NULL);
15261 return (ctxt->err);
15262 }
15263 /*
15264 * cvc-elt (3.3.4) : 2
15265 */
15266 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15267 xmlSchemaVCustomErr(ctxt,
15268 XML_SCHEMAV_CVC_ELT_2,
15269 elem, NULL,
15270 "The element declaration is abstract", NULL);
15271 return (ctxt->err);
15272 }
15273
15274 /*
15275 * cvc-elt (3.3.4) : 3
15276 * Handle 'xsi:nil'.
15277 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015278
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015279 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015280 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015281 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15282 ctxt->node = (xmlNodePtr) attr;
15283 ctxt->cur = attr->children;
15284 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15285 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15286 BAD_CAST attrValue, 1, 1, 1, 1);
15287 ctxt->node = elem;
15288 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15289 if (ret < 0) {
15290 xmlSchemaVCustomErr(ctxt,
15291 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015292 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015293 "Internal error: xmlSchemaValidateElementByDeclaration, "
15294 "validating the attribute 'xsi:nil'", NULL);
15295 if (attrValue != NULL)
15296 xmlFree(attrValue);
15297 return (-1);
15298 }
15299 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015300 /*
15301 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015302 */
15303 xmlSchemaVCustomErr(ctxt,
15304 XML_SCHEMAV_CVC_ELT_3_1,
15305 elem, NULL,
15306 "The element is not 'nillable'", NULL);
15307 } else {
15308 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015309 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015310 ret = 0;
15311 /*
15312 * cvc-elt (3.3.4) : 3.2.1
15313 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015314 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15315 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015316 xmlSchemaVCustomErr(ctxt,
15317 XML_SCHEMAV_CVC_ELT_3_2_1,
15318 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015319 elem, (xmlSchemaTypePtr) elemDecl,
15320 "The 'nilled' element must have no character or "
15321 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015322 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15323 }
15324 /*
15325 * cvc-elt (3.3.4) : 3.2.2
15326 */
15327 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15328 (elemDecl->value != NULL)) {
15329 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15330 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015331 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015332 "There is a fixed value constraint defined for "
15333 "the 'nilled' element", NULL);
15334 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15335 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015336 if (ret == 0)
15337 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015338 }
15339 }
15340 if (attrValue != NULL)
15341 xmlFree(attrValue);
15342 }
15343
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015344
15345 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015346 /*
15347 * cvc-elt (3.3.4) : 4
15348 * Handle 'xsi:type'.
15349 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015350
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015351 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15352 if (attr != NULL) {
15353 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015354
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015355 /*
15356 * TODO: We should report a *warning* that the type was overriden
15357 * by the instance.
15358 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015359
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015360 /*
15361 * cvc-elt (3.3.4) : 4.1
15362 */
15363 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15364 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15365 &nsName, &local);
15366 if (ret < 0) {
15367 xmlSchemaVCustomErr(ctxt,
15368 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015369 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015370 "Internal error: xmlSchemaValidateElementByDeclaration, "
15371 "validating the attribute 'xsi:type'", NULL);;
15372 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015373 FREE_AND_NULL(nsName)
15374 FREE_AND_NULL(local)
15375 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015376 } else if (ret == 1) {
15377 xmlSchemaVSimpleTypeErr(ctxt,
15378 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15379 (xmlNodePtr) attr, attrValue,
15380 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15381 } else if (ret == 2) {
15382 xmlSchemaVCustomErr(ctxt,
15383 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15384 (xmlNodePtr) attr,
15385 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15386 "The QName value '%s' has no "
15387 "corresponding namespace declaration in scope",
15388 attrValue);
15389 } else {
15390 /*
15391 * cvc-elt (3.3.4) : 4.2
15392 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015393 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15394 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015395 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015396
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015397 xmlSchemaVCustomErr(ctxt,
15398 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015399 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015400 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15401 "The value %s does not resolve to a type "
15402 "definition",
15403 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15404 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015405 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015406 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015407 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015408 */
15409 }
15410 }
15411 FREE_AND_NULL(attrValue)
15412 FREE_AND_NULL(nsName)
15413 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015414 }
15415 /* TODO: Change the handling of missing types according to
15416 * the spec.
15417 */
15418 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015419 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015420 XML_SCHEMAV_CVC_TYPE_1,
15421 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015422 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015423 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015424 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015425
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015426 /*
15427 * TODO: Since this should be already checked by the content model automaton,
15428 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15429 * has been changed to XML_SCHEMAV_INTERNAL.
15430 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015431 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015432 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015433 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015434 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015435 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015436 "Element %s: missing child %s\n",
15437 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015438 }
15439 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015440 }
15441 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015442 /*
15443 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015444 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015445 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015446 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015447 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015448 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015449 "Element %s: missing child %s found %s\n",
15450 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015451 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015452 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015453 */
15454 if (elemHasContent == -1)
15455 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15456 /*
15457 * cvc-elt (3.3.4) : 5
15458 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015459 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015460 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015461 * cvc-elt (3.3.4) : 5.1
15462 * If the declaration has a {value constraint},
15463 * the item has neither element nor character [children] and
15464 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015465 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015466 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15467 /*
15468 * cvc-elt (3.3.4) : 5.1.1
15469 * If the ·actual type definition· is a ·local type definition·
15470 * then the canonical lexical representation of the {value constraint}
15471 * value must be a valid default for the ·actual type definition· as
15472 * defined in Element Default Valid (Immediate) (§3.3.6).
15473 */
15474 /*
15475 * NOTE: 'local' above means types aquired by xsi:type.
15476 */
15477 ret = 0;
15478 if (actualType != elemDecl->subtypes) {
15479 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15480 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15481 elemDecl->value, NULL);
15482 if (ret < 0) {
15483 xmlSchemaVCustomErr(ctxt,
15484 XML_SCHEMAV_INTERNAL,
15485 elem, actualType,
15486 "Internal error: xmlSchemaValidateElementByDeclaration, "
15487 "validating a default value", NULL);
15488 return (-1);
15489 }
15490 }
15491 /*
15492 * cvc-elt (3.3.4) : 5.1.2
15493 * The element information item with the canonical lexical
15494 * representation of the {value constraint} value used as its
15495 * ·normalized value· must be ·valid· with respect to the
15496 * ·actual type definition· as defined by Element Locally Valid (Type)
15497 * (§3.3.4).
15498 */
15499 /*
15500 * Disable validation of the simple content, since it was already
15501 * done above.
15502 */
15503 if (ret == 0) {
15504 if (actualType != elemDecl->subtypes)
15505 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15506 else
15507 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15508 ctxt->node = elem;
15509 if (ret < 0) {
15510 xmlSchemaVCustomErr(ctxt,
15511 XML_SCHEMAV_INTERNAL,
15512 elem, actualType,
15513 "Internal error: xmlSchemaValidateElementByDeclaration, "
15514 "validating against the type", NULL);
15515 return (-1);
15516 }
15517 /*
15518 * PSVI: Create a text node on the instance element.
15519 */
15520 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15521 xmlNodePtr textChild;
15522
15523 textChild = xmlNewText(elemDecl->value);
15524 if (textChild == NULL) {
15525 xmlSchemaVCustomErr(ctxt,
15526 XML_SCHEMAV_INTERNAL,
15527 elem, actualType,
15528 "Internal error: xmlSchemaValidateElementByDeclaration, "
15529 "could not create a default text node for the instance",
15530 NULL);
15531 } else
15532 xmlAddChild(elem, textChild);
15533 }
15534 }
15535
15536 } else {
15537 /*
15538 * 5.2.1 The element information item must be ·valid· with respect
15539 * to the ·actual type definition· as defined by Element Locally
15540 * Valid (Type) (§3.3.4).
15541 */
15542 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15543 ctxt->node = elem;
15544 if (ret < 0) {
15545 xmlSchemaVCustomErr(ctxt,
15546 XML_SCHEMAV_INTERNAL,
15547 elem, actualType,
15548 "Internal error: xmlSchemaValidateElementByDeclaration, "
15549 "validating a default value", NULL);
15550 return (-1);
15551 }
15552 /*
15553 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15554 * not applied, all of the following must be true:
15555 */
15556
15557 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15558 /*
15559 * 5.2.2.1 The element information item must have no element
15560 * information item [children].
15561 *
15562 * TODO REDUNDANT: If the actual type exists, the above call to
15563 * xmlSchemaValidateElementByType will already check for element
15564 * nodes.
15565 */
15566 if (xmlSchemaHasElemContent(elem)) {
15567 xmlSchemaVCustomErr(ctxt,
15568 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15569 elem, (xmlSchemaTypePtr) elemDecl,
15570 "Elements in the content are not allowed if it is "
15571 "constrained by a fixed value", NULL);
15572 } else {
15573 /*
15574 * 5.2.2.2 The appropriate case among the following must
15575 * be true:
15576 */
15577
15578 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15579 xmlChar *value;
15580 /*
15581 * 5.2.2.2.1 If the {content type} of the ·actual type
15582 * definition· is mixed, then the *initial value* of the
15583 * item must match the canonical lexical representation
15584 * of the {value constraint} value.
15585 *
15586 * ... the *initial value* of an element information
15587 * item is the string composed of, in order, the
15588 * [character code] of each character information item in
15589 * the [children] of that element information item.
15590 */
15591 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15592 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15593 /*
15594 * TODO: Report invalid & expected values as well.
15595 * TODO: Implement the cononical stuff.
15596 */
15597 xmlSchemaVCustomErr(ctxt,
15598 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15599 elem, (xmlSchemaTypePtr) elemDecl,
15600 "The value does not match the cononical "
15601 "lexical representation of the fixed constraint",
15602 NULL);
15603 }
15604 if (value != NULL)
15605 xmlFree(value);
15606 } else if ((actualType->contentType ==
15607 XML_SCHEMA_CONTENT_SIMPLE) ||
15608 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15609 xmlChar *value;
15610
15611 /*
15612 * 5.2.2.2.2 If the {content type} of the ·actual type
15613 * definition· is a simple type definition, then the
15614 * *actual value* of the item must match the canonical
15615 * lexical representation of the {value constraint} value.
15616 */
15617 /*
15618 * TODO: *actual value* is the normalized value, impl. this.
15619 * TODO: Report invalid & expected values as well.
15620 * TODO: Implement the cononical stuff.
15621 *
15622 */
15623 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15624 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15625 xmlSchemaVCustomErr(ctxt,
15626 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15627 elem, (xmlSchemaTypePtr) elemDecl,
15628 "The normalized value does not match the cononical "
15629 "lexical representation of the fixed constraint",
15630 NULL);
15631 }
15632 if (value != NULL)
15633 xmlFree(value);
15634
15635 }
15636 /*
15637 * TODO: What if the content type is not 'mixed' or simple?
15638 */
15639
15640 }
15641
15642 }
15643 }
15644
15645 /*
15646 * TODO: 6 The element information item must be ·valid· with respect to each of
15647 * the {identity-constraint definitions} as per Identity-constraint
15648 * Satisfied (§3.11.4).
15649 */
15650
15651 /*
15652 * TODO: 7 If the element information item is the ·validation root·, it must be
15653 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15654 */
15655
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015656 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015657}
15658
Daniel Veillard4255d502002-04-16 15:50:10 +000015659/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015660 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015661 * @ctxt: a schema validation context
15662 * @node: the top node.
15663 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015664 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15665 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015666 *
15667 * Returns 0 if the element is valid, a positive error code
15668 * number otherwise and -1 in case of an internal error.
15669 */
15670static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015671xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15672 xmlSchemaWildcardPtr wild,
15673 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015674{
15675 const xmlChar *uri;
15676 int ret = 0;
15677 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015678
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015679 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015680 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15681 if (ret == -1) {
15682 xmlSchemaVCustomErr(ctxt,
15683 XML_SCHEMAV_INTERNAL,
15684 ctxt->node, NULL,
15685 "Internal error: xmlSchemaValidateElement, "
15686 "assembling schema by xsi", NULL);
15687 return (-1);
15688 }
15689 /*
15690 * NOTE: We won't react on schema parser errors here.
15691 * TODO: But a warning would be nice.
15692 */
15693 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015694 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15695 xmlSchemaElementPtr decl = NULL;
15696
15697 if (node->ns != NULL)
15698 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15699 node->name, node->ns->href, NULL);
15700 else
15701 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15702 if (decl != NULL) {
15703 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015704 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015705 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015706 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015707 "Internal error: xmlSchemaValidateAnyInternal, "
15708 "validating an element in the context of a wildcard.",
15709 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000015710 }
15711 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015712 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15713 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015714 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015715 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015716 return (ctxt->err);
15717 }
15718 }
15719 if (node->children != NULL) {
15720 child = node->children;
15721 do {
15722 if (child->type == XML_ELEMENT_NODE) {
15723 if (child->ns != NULL)
15724 uri = child->ns->href;
15725 else
15726 uri = NULL;
15727 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015728 /* TODO: error code. */
15729 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015730 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015731 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015732 return (ctxt->err);
15733 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015734 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15735 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015736 if (ret != 0)
15737 return (ret);
15738 }
15739 child = child->next;
15740 } while (child != NULL);
15741 }
15742 return (0);
15743}
15744
15745/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015746 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015747 * @ctxt: a schema validation context
15748 *
15749 * Returns 0 if the element is valid, a positive error code
15750 * number otherwise and -1 in case of an internal or API error.
15751 */
15752static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015753xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15754 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015755{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015756 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15757 (ctxt->node == NULL)) {
15758 xmlSchemaVCustomErr(ctxt,
15759 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15760 "Internal error: xmlSchemaValidateElementByWildcard, "
15761 "bad arguments", NULL);
15762 return (-1);
15763 }
15764 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15765 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015766}
15767
15768/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015769 * xmlSchemaValidateAnyTypeContent:
15770 * @ctxt: a schema validation context
15771 * @node: the current element
15772 *
15773 * This one validates the content of an element of the type
15774 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15775 * thus elements in the subtree will be validated, if a corresponding
15776 * declaration in the schema exists.
15777 *
15778 * Returns 0 if the element and its subtree is valid, a positive error code
15779 * otherwise and -1 in case of an internal or API error.
15780 */
15781static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015782xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15783 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015784{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015785 xmlSchemaTypePtr oldtype;
15786 xmlNodePtr top, cur;
15787 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015788 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015789
15790 if ((type == NULL) || (ctxt->node == NULL))
15791 return (-1);
15792
15793 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015794 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015795
15796 oldtype = ctxt->type;
15797 top = ctxt->node;
15798 /*
15799 * STREAM: Child nodes are processed.
15800 */
15801 cur = ctxt->node->children;
15802 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015803 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015804 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015805 /*
15806 * The process contents of the wildcard is "lax", thus
15807 * we need to validate the element if a declaration
15808 * exists.
15809 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015810 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015811 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015812 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015813 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015814 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015815 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015816 ctxt->node = cur;
15817 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15818 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015819 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015820 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015821 "Internal error: xmlSchemaValidateAnyTypeContent, "
15822 "validating an element in the context of a wildcard.",
15823 NULL, NULL);
15824 return (ret);
15825 } else if (ret > 0)
15826 return (ret);
15827 skipContent = 1;
15828 }
15829 }
15830 /*
15831 * Browse the full subtree, deep first.
15832 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015833 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015834 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015835 cur = cur->children;
15836 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015837 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015838 cur = cur->next;
15839 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015840 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015841 while (cur != top) {
15842 if (cur->parent != NULL)
15843 cur = cur->parent;
15844 if ((cur != top) && (cur->next != NULL)) {
15845 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015846 break;
15847 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015848 if (cur->parent == NULL) {
15849 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015850 break;
15851 }
15852 }
15853 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015854 if (cur == top)
15855 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015856 } else
15857 break;
15858 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015859 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015860 return (0);
15861}
15862
15863/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015864 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015865 * @ctxt: a schema validation context
15866 * @node: the top node.
15867 *
15868 * Validate the content of an element expected to be a complex type type
15869 * xmlschema-1.html#cvc-complex-type
15870 * Validation Rule: Element Locally Valid (Complex Type)
15871 *
15872 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015873 * number otherwise and -1 in case of internal or API error.
15874 * Note on reported errors: Although it might be nice to report
15875 * the name of the simple/complex type, used to validate the content
15876 * of a node, it is quite unnecessary: for global defined types
15877 * the local name of the element is equal to the NCName of the type,
15878 * for local defined types it makes no sense to output the internal
15879 * computed name of the type. TODO: Instead, one should attach the
15880 * struct of the type involved to the error handler - this allows
15881 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015882 */
15883static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015884xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015885 xmlSchemaTypePtr type,
15886 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015887{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015888 xmlSchemaTypePtr oldtype;
15889 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015890 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015891 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015892 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015893
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015894 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15895 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015896
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015897 oldtype = ctxt->type;
15898 ctxt->type = type;
15899 elem = ctxt->node;
15900
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015901 /*
15902 * Verify the attributes
15903 */
15904 /*
15905 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015906 */
15907 /* NOTE: removed, since a check for abstract is
15908 * done in the cvc-type constraint.
15909 *
15910 *
15911 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15912 * xmlSchemaVComplexTypeErr(ctxt,
15913 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15914 * elem, type,
15915 * "The type definition is abstract");
15916 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15917 *}
15918 */
15919
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015920 attrs = ctxt->attr;
15921 attrTop = ctxt->attrTop;
15922 /*
15923 * STREAM: Attribute nodes are processed.
15924 */
15925 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15926 xmlSchemaValidateAttributes(ctxt, elem, type);
15927 if (ctxt->attr != NULL)
15928 xmlSchemaFreeAttributeStates(ctxt->attr);
15929 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015930 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015931
15932 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015933 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015934 * model was defined. Somehow ->contModel is always not NULL
15935 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015936 * TODO: Check if the obove still occurs.
15937 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015938 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015939 case XML_SCHEMA_CONTENT_EMPTY: {
15940 /*
15941 * 1 If the {content type} is empty, then the element information
15942 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015943 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015944 /*
15945 * TODO: Is the entity stuff correct?
15946 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015947 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015948 xmlSchemaVComplexTypeErr(ctxt,
15949 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015950 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015951 "Character or element content is not allowed, "
15952 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015953 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015954 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015955 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015956 case XML_SCHEMA_CONTENT_MIXED:
15957 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015958 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015959 /*
15960 * The type has 'anyType' as its base and no content model
15961 * is defined -> use 'anyType' as the type to validate
15962 * against.
15963 */
15964 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15965 /* TODO: Handle -1. */
15966 break;
15967 }
15968 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015969 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015970 {
15971 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000015972 xmlChar *values[10];
15973 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015974
15975 /*
15976 * Content model check initialization.
15977 */
15978 if (type->contModel != NULL) {
15979 oldregexp = ctxt->regexp;
15980 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15981 (xmlRegExecCallbacks)
15982 xmlSchemaValidateCallback, ctxt);
15983#ifdef DEBUG_AUTOMATA
15984 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15985#endif
15986 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015987 /*
15988 * STREAM: Children are processed.
15989 */
15990 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015991 while (child != NULL) {
15992 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015993 if (child->ns != NULL)
15994 nsUri = child->ns->href;
15995 else
15996 nsUri = NULL;
15997 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015998 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015999 /*
16000 * URGENT TODO: Could we anchor an error report
16001 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016002 * TODO: Perhaps it would be better to report
16003 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016004 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016005#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000016006 if (ret < 0)
16007 xmlGenericError(xmlGenericErrorContext,
16008 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000016009 else
16010 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016011 " --> %s\n", child->name);
16012#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016013 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016014 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
16015 &values[0], &terminal);
16016 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016017 XML_SCHEMAV_ELEMENT_CONTENT,
16018 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016019 "This element is not expected",
16020 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016021 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016022 /*
16023 * Note that this will skip further validation of the
16024 * content.
16025 */
16026 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016027 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016028 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
16029 /*
16030 * TODO: Ask Daniel if this are all character nodes.
16031 */
16032 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
16033 (child->type == XML_ENTITY_NODE) ||
16034 (child->type == XML_ENTITY_REF_NODE) ||
16035 (child->type == XML_CDATA_SECTION_NODE))) {
16036 /*
16037 * 2.3 If the {content type} is element-only, then the
16038 * element information item has no character information
16039 * item [children] other than those whose [character
16040 * code] is defined as a white space in [XML 1.0 (Second
16041 * Edition)].
16042 */
William M. Brack2f2a6632004-08-20 23:09:47 +000016043 xmlSchemaVComplexTypeErr(ctxt,
16044 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016045 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016046 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016047 "because the content type is element-only");
16048 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016049 break;
16050 }
16051 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016052 }
16053 /*
16054 * Content model check finalization.
16055 */
16056 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016057 if (ret == 0) {
16058 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
16059 &values[0], &terminal);
16060 if (nbval + nbneg != 0) {
16061 /*
16062 * If a next value still exists, I does not have to
16063 * mean that there's an element missing, since it
16064 * might be an optional element. So double check it.
16065 */
16066 ret = xmlRegExecPushString(ctxt->regexp,
16067 NULL, NULL);
16068 if (ret <= 0) {
16069 ret = 1;
16070 xmlSchemaVComplexTypeElemErr(ctxt,
16071 XML_SCHEMAV_ELEMENT_CONTENT,
16072 elem, type, "Missing child element(s)",
16073 nbval, nbneg, values);
16074 } else
16075 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016076#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016077 xmlGenericError(xmlGenericErrorContext,
16078 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016079#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016080 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016081#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016082 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016083 xmlGenericError(xmlGenericErrorContext,
16084 "Element %s content check succeeded\n",
16085 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016086#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016087 }
16088 xmlRegFreeExecCtxt(ctxt->regexp);
16089 ctxt->regexp = oldregexp;
16090 }
16091 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016092 break;
16093 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016094 case XML_SCHEMA_CONTENT_BASIC:
16095 /*
16096 * If the simple content was already validated
16097 * (e.g. a default value), the content need not
16098 * to be validated again.
16099 */
16100 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016101 xmlChar *value = NULL;
16102 /*
16103 * We hit a complexType with a simpleContent resolving
16104 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000016105 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016106 /*
16107 * 2.2 If the {content type} is a simple type definition,
16108 * then the element information item has no element
16109 * information item [children], and the ·normalized value·
16110 * of the element information item is ·valid· with respect
16111 * to that simple type definition as defined by String
16112 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016113 */
16114 /*
16115 * STREAM: Children are processed.
16116 */
16117 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016118 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016119 /*
16120 * TODO: Could the entity stuff produce elements
16121 * as well?
16122 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016123 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016124 xmlSchemaVComplexTypeErr(ctxt,
16125 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016126 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016127 "Element content is not allowed, because "
16128 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016129 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16130 break;
16131 }
16132 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016133 }
16134 ctxt->node = elem;
16135 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016136 if (ret == 0) {
16137 /*
16138 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000016139 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016140 /*
16141 * STREAM: Children are processed.
16142 */
16143 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016144 value = NULL;
16145 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016146 value = xmlNodeGetContent(elem);
16147 /*
16148 * URGENT TODO: Should facets for the simple type validation be
16149 * disabled, if the derivation of facets for complex types
16150 * is implemented?
16151 */
16152 /*
16153 * NOTE: This call won't check the correct types of the
16154 * content nodes, since this should be done here.
16155 */
16156 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016157 if (ret > 0) {
16158 /*
16159 * NOTE: Although an error will be reported by
16160 * xmlSchemaValidateSimpleTypeValue, the spec wants
16161 * a specific complex type error to be reported
16162 * additionally.
16163 */
16164 xmlSchemaVComplexTypeErr(ctxt,
16165 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016166 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016167 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016168 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16169 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016170 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016171 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016172 "Element '%s': Error while validating character "
16173 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016174 elem->name, type->name);
16175 if (value != NULL)
16176 xmlFree(value);
16177 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016178 return (-1);
16179 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016180 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016181 if (ret == 0) {
16182 /*
16183 * Apply facets of the complexType. Be sure to pass the
16184 * built-in type to xmlSchemaValidateFacetsInternal.
16185 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016186 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000016187 * are used, or if the facets, defined by this complex type,
16188 * are to be used only. This here applies both facet sets.
16189 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016190
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016191 ret = xmlSchemaValidateFacetsInternal(ctxt,
16192 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016193 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016194 xmlSchemaVComplexTypeErr(ctxt,
16195 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016196 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016197 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016198 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16199 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016200 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016201 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016202 "Element '%s': Error while validating character "
16203 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000016204 "apply facets.\n",
16205 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016206 if (value != NULL)
16207 xmlFree(value);
16208 ctxt->type = oldtype;
16209 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016210 }
16211 }
16212 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000016213 xmlFree(value);
16214
Daniel Veillard01fa6152004-06-29 17:04:39 +000016215 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016216 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016217 default:
16218 TODO xmlGenericError(xmlGenericErrorContext,
16219 "unimplemented content type %d\n",
16220 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016221 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016222 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016223 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016224}
16225
16226/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016227 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016228 * @ctxt: a schema validation context
16229 * @elem: an element
16230 * @type: the list of type declarations
16231 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016232 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016233 *
16234 * Returns 0 if the element is schemas valid, a positive error code
16235 * number otherwise and -1 in case of internal or API error.
16236 */
16237static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016238xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016239 xmlSchemaTypePtr type,
16240 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016241{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016242 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016243
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016244
16245 if ((ctxt == NULL) || (type == NULL)) {
16246 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16247 "Internal error: xmlSchemaValidateElementByType, "
16248 "bad arguments", NULL);
16249 return (-1);
16250 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016251 /*
16252 * This one is called by "xmlSchemaValidateElementByDeclaration".
16253 * It will forward to the proper validation
16254 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016255 */
16256 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016257 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016258 XML_SCHEMAV_CVC_TYPE_1,
16259 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016260 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016261 return (XML_SCHEMAV_CVC_TYPE_1);
16262 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016263
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016264 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016265 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016266 XML_SCHEMAV_CVC_TYPE_2,
16267 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016268 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016269 return (XML_SCHEMAV_CVC_TYPE_2);
16270 }
16271
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016272 switch (type->type) {
16273 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016274 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16275 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016276 break;
16277 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016278 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16279 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016280 break;
16281 case XML_SCHEMA_TYPE_BASIC:
16282 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16283 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16284 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016285 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16286 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016287 break;
16288 default:
16289 ret = -1;
16290 break;
16291 }
16292 if (ret == -1)
16293 return (-1);
16294 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016295 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016296}
16297
16298
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016299static int
16300xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16301 xmlSchemaAttributePtr decl,
16302 xmlSchemaAttrStatePtr state,
16303 xmlAttrPtr attr)
16304{
16305 xmlChar *value;
16306 const xmlChar *defValue;
16307 xmlSchemaValPtr defVal;
16308 int fixed;
16309 int ret;
16310
16311 if (decl->subtypes == NULL) {
16312 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16313 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16314 }
16315 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16316 ctxt->node = (xmlNodePtr) attr;
16317 ctxt->cur = attr->children;
16318 /*
16319 * NOTE: This call also checks the content nodes for correct type.
16320 */
16321 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16322 value, 1, 1, 1, 1);
16323
16324 /*
16325 * Handle 'fixed' attributes.
16326 */
16327 if (ret > 0) {
16328 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16329 /*
16330 * NOTE: Fixed value constraints will be not
16331 * applied if the value was invalid, because:
16332 * 1. The validation process does not return a precomputed
16333 * value.
16334 * 2. An invalid value implies a violation of a fixed
16335 * value constraint.
16336 */
16337 } else if (ret == 0) {
16338 state->state = XML_SCHEMAS_ATTR_CHECKED;
16339 if (xmlSchemaGetEffectiveValueConstraint(decl,
16340 &fixed, &defValue, &defVal) && (fixed == 1)) {
16341 /*
16342 * cvc-au : Attribute Locally Valid (Use)
16343 * For an attribute information item to be·valid·
16344 * with respect to an attribute use its ·normalized
16345 * value· must match the canonical lexical representation
16346 * of the attribute use's {value constraint} value, if it
16347 * is present and fixed.
16348 */
16349 /*
16350 * NOTE: the validation context holds in ctxt->value the
16351 * precomputed value of the attribute; well for some types,
16352 * fallback to string comparison if no computed value
16353 * exists.
16354 */
16355 if (((ctxt->value != NULL) &&
16356 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16357 ((ctxt->value == NULL) &&
16358 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16359 state->state =
16360 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16361 }
16362 }
16363 }
16364 if (value != NULL) {
16365 xmlFree(value);
16366 }
16367 return (ret);
16368}
16369
Daniel Veillard4255d502002-04-16 15:50:10 +000016370/**
16371 * xmlSchemaValidateAttributes:
16372 * @ctxt: a schema validation context
16373 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016374 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016375 *
16376 * Validate the attributes of an element.
16377 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016378 * 1. Existent, invalid attributes are reported in the form
16379 * "prefix:localName".
16380 * Reason: readability - it is easier to find the actual XML
16381 * representation of the attributes QName.
16382 * 2. Missing attributes are reported in the form
16383 * {"URI", "localName"}.
16384 * This is necessary, since the the prefix need not to be declared
16385 * at all, and thus is not computable.
16386 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016387 * Returns 0 if the element is schemas valid, a positive error code
16388 * number otherwise and -1 in case of internal or API error.
16389 */
16390static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016391xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016392{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016393 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016394 int ret;
16395 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016396 const xmlChar *defValue;
16397 xmlSchemaValPtr defVal;
16398 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016399 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016400 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016401 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016402 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016403 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016404 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016405#ifdef DEBUG_ATTR_VALIDATION
16406 int redundant = 0;
16407#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016408
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016409
Daniel Veillardc0826a72004-08-10 14:17:33 +000016410 /*
16411 * Allow all attributes if the type is anyType.
16412 */
16413 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16414 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016415
16416 oldnode = ctxt->node;
16417 if (type != NULL)
16418 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016419 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016420 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016421 attrDecl = attrUse->attr;
16422#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016423 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016424 printf("attr use - use: %d\n", attrDecl->occurs);
16425#endif
16426 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16427
16428 if (curState->decl == attrUse->attr) {
16429#ifdef DEBUG_ATTR_VALIDATION
16430 redundant = 1;
16431#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016432 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016433 attr = curState->attr;
16434#ifdef DEBUG_ATTR_VALIDATION
16435 printf("attr - name: %s\n", attr->name);
16436 if (attr->ns != NULL)
16437 printf("attr - ns: %s\n", attr->ns->href);
16438 else
16439 printf("attr - ns: none\n");
16440#endif
16441 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016442 if (attr == NULL)
16443 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016444 if (attrDecl->ref != NULL) {
16445 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016446 continue;
16447 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016448 if ((attrDecl->refNs == NULL) ||
16449 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016450 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016451 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016452 continue;
16453 }
16454 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016455 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016456 continue;
16457 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016458 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016459 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016460 if (attr->ns == NULL) {
16461 /*
William M. Bracke7091952004-05-11 15:09:58 +000016462 * accept an unqualified attribute only if the target
16463 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016464 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016465 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016466 /*
16467 * This check was removed, since the target namespace
16468 * was evaluated during parsing and already took
16469 * "attributeFormDefault" into account.
16470 */
16471 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016472 continue;
16473 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016474 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016475 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016476 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016477 attr->ns->href))
16478 continue;
16479 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016480 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016481#ifdef DEBUG_ATTR_VALIDATION
16482 printf("found\n");
16483#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016484 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016485 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016486 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016487 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016488 if (!found) {
16489 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16490 xmlSchemaAttrStatePtr tmp;
16491
Daniel Veillard3646d642004-06-02 19:19:14 +000016492#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016493 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016494#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016495 /*
16496 * Add a new dummy attribute state.
16497 */
16498 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16499 if (tmp == NULL) {
16500 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16501 ctxt->node = oldnode;
16502 return (-1);
16503 }
16504 tmp->attr = NULL;
16505 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16506 tmp->decl = attrDecl;
16507 tmp->next = NULL;
16508
16509 if (reqAttrStates == NULL) {
16510 reqAttrStates = tmp;
16511 reqAttrStatesTop = tmp;
16512 } else {
16513 reqAttrStatesTop->next = tmp;
16514 reqAttrStatesTop = tmp;
16515 }
16516 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16517 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16518 &fixed, &defValue, &defVal))) {
16519 xmlSchemaAttrStatePtr tmp;
16520 /*
16521 * Handle non existent default/fixed attributes.
16522 */
16523 tmp = (xmlSchemaAttrStatePtr)
16524 xmlMalloc(sizeof(xmlSchemaAttrState));
16525 if (tmp == NULL) {
16526 xmlSchemaVErrMemory(ctxt,
16527 "registering schema specified attributes", NULL);
16528 ctxt->node = oldnode;
16529 return (-1);
16530 }
16531 tmp->attr = NULL;
16532 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16533 tmp->decl = attrDecl;
16534 tmp->value = defValue;
16535 tmp->next = NULL;
16536
16537 if (defAttrStates == NULL) {
16538 defAttrStates = tmp;
16539 defAttrStates = tmp;
16540 } else {
16541 defAttrStates->next = tmp;
16542 defAttrStatesTop = tmp;
16543 }
16544 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016545 }
16546 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016547 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016548 /*
16549 * Add required attributes to the attribute states of the context.
16550 */
16551 if (reqAttrStates != NULL) {
16552 if (ctxt->attr == NULL) {
16553 ctxt->attr = reqAttrStates;
16554 } else {
16555 ctxt->attrTop->next = reqAttrStates;
16556 }
16557 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016558 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016559 /*
16560 * Process wildcards.
16561 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016562
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016563 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016564#ifdef DEBUG_ATTR_VALIDATION
16565 xmlSchemaWildcardNsPtr ns;
16566 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016567 if (type->attributeWildcard->processContents ==
16568 XML_SCHEMAS_ANY_LAX)
16569 printf("processContents: lax\n");
16570 else if (type->attributeWildcard->processContents ==
16571 XML_SCHEMAS_ANY_STRICT)
16572 printf("processContents: strict\n");
16573 else
16574 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016575 if (type->attributeWildcard->any)
16576 printf("type: any\n");
16577 else if (type->attributeWildcard->negNsSet != NULL) {
16578 printf("type: negated\n");
16579 if (type->attributeWildcard->negNsSet->value == NULL)
16580 printf("ns: (absent)\n");
16581 else
16582 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16583 } else if (type->attributeWildcard->nsSet != NULL) {
16584 printf("type: set\n");
16585 ns = type->attributeWildcard->nsSet;
16586 while (ns != NULL) {
16587 if (ns->value == NULL)
16588 printf("ns: (absent)\n");
16589 else
16590 printf("ns: %s\n", ns->value);
16591 ns = ns->next;
16592 }
16593 } else
16594 printf("empty\n");
16595
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016596
16597#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016598 curState = ctxt->attr;
16599 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016600 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16601 if (curState->attr->ns != NULL)
16602 nsURI = curState->attr->ns->href;
16603 else
16604 nsURI = NULL;
16605 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16606 nsURI)) {
16607 /*
16608 * Handle processContents.
16609 */
16610 if ((type->attributeWildcard->processContents ==
16611 XML_SCHEMAS_ANY_LAX) ||
16612 (type->attributeWildcard->processContents ==
16613 XML_SCHEMAS_ANY_STRICT)) {
16614
16615 attr = curState->attr;
16616 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016617 attr->name, nsURI);
16618 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016619 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016620 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016621 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016622 } else if (type->attributeWildcard->processContents ==
16623 XML_SCHEMAS_ANY_LAX) {
16624 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16625 }
16626 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016627 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016628 }
16629 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016630 curState = curState->next;
16631 }
16632 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016633
Daniel Veillardc0826a72004-08-10 14:17:33 +000016634 /*
16635 * Report missing and illegal attributes.
16636 */
16637 if (ctxt->attr != NULL) {
16638 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016639 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016640 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16641 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016642 if (curState->decl != NULL) {
16643 if (curState->decl->ref != NULL)
16644 attrDecl = curState->decl->refDecl;
16645 else
16646 attrDecl = curState->decl;
16647 } else
16648 attrDecl = NULL;
16649 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16650 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16651 } else if (curState->state ==
16652 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16653 xmlSchemaVCustomErr(ctxt,
16654 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16655 (xmlNodePtr) attr,
16656 (xmlSchemaTypePtr) attrDecl,
16657 "The type definition is absent",
16658 NULL);
16659 } else if (curState->state ==
16660 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16661 xmlSchemaVCustomErr(ctxt,
16662 XML_SCHEMAV_CVC_AU,
16663 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16664 "The value does not match the fixed value "
16665 "constraint", NULL);
16666 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016667 /* TODO: "prohibited" won't ever be touched here!.
16668 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16669 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016670 /*
16671 * TODO: One might report different error messages
16672 * for the following errors.
16673 */
16674 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016675 xmlSchemaVIllegalAttrErr(ctxt,
16676 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16677 } else {
16678 xmlSchemaVIllegalAttrErr(ctxt,
16679 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16680 }
16681 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016682 }
16683 curState = curState->next;
16684 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016685 }
16686
16687 /*
16688 * Add missing default/fixed attributes.
16689 */
16690 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16691 curState = defAttrStates;
16692 while (curState != NULL) {
16693 attrDecl = curState->decl;
16694 if (attrDecl->ref != NULL)
16695 attrDecl = attrDecl->refDecl;
16696 /*
16697 * PSVI: Add a new attribute node to the current element.
16698 */
16699 if (attrDecl->targetNamespace == NULL) {
16700 xmlNewProp(elem, attrDecl->name, curState->value);
16701 } else {
16702 xmlNsPtr ns;
16703
16704 ns = xmlSearchNsByHref(elem->doc, elem,
16705 attrDecl->targetNamespace);
16706 if (ns == NULL) {
16707 xmlChar prefix[12];
16708 int counter = 1;
16709
16710 attr = curState->attr;
16711 /*
16712 * Create a namespace declaration on the validation
16713 * root node if no namespace declaration is in scope.
16714 */
16715 snprintf((char *) prefix, sizeof(prefix), "p");
16716 /*
16717 * This is somehow not performant, since the ancestor
16718 * axis beyond @elem will be searched as well.
16719 */
16720 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16721 while (ns != NULL) {
16722 if (counter > 1000) {
16723 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16724 XML_SCHEMAV_INTERNAL,
16725 "Internal error: xmlSchemaValidateAttributes, "
16726 "could not compute a ns prefix for "
16727 "default/fixed attribute '%s'.\n",
16728 attrDecl->name, NULL);
16729
16730 break;
16731 }
16732 snprintf((char *) prefix,
16733 sizeof(prefix), "p%d", counter++);
16734 ns = xmlSearchNs(elem->doc, elem,
16735 BAD_CAST prefix);
16736 }
16737 if (ns == NULL) {
16738 ns = xmlNewNs(ctxt->validationRoot,
16739 attrDecl->targetNamespace, BAD_CAST prefix);
16740 xmlNewNsProp(elem, ns, attrDecl->name,
16741 curState->value);
16742 }
16743 } else {
16744 xmlNewNsProp(elem, ns, attrDecl->name,
16745 curState->value);
16746 }
16747 }
16748 curState = curState->next;
16749 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016750 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016751 if (defAttrStates != NULL)
16752 xmlSchemaFreeAttributeStates(defAttrStates);
16753
Daniel Veillard3646d642004-06-02 19:19:14 +000016754#ifdef DEBUG_ATTR_VALIDATION
16755 if (redundant)
16756 xmlGenericError(xmlGenericErrorContext,
16757 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16758 type->name);
16759#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016760 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016761 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016762}
16763
16764/**
16765 * xmlSchemaValidateElement:
16766 * @ctxt: a schema validation context
16767 * @elem: an element
16768 *
16769 * Validate an element in a tree
16770 *
16771 * Returns 0 if the element is schemas valid, a positive error code
16772 * number otherwise and -1 in case of internal or API error.
16773 */
16774static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016775xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016776{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016777 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016778 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016779
Daniel Veillardc0826a72004-08-10 14:17:33 +000016780 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016781 * This one is called by xmlSchemaValidateDocument and
16782 * xmlSchemaValidateOneElement.
16783 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016784 if (ctxt->schema == NULL) {
16785 /*
16786 * No schema was specified at time of creation of the validation
16787 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16788 * of the instance to build a schema.
16789 */
16790 if (ctxt->pctxt == NULL)
16791 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16792 if (ctxt->pctxt == NULL)
16793 return (-1);
16794 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16795 if (ctxt->schema == NULL)
16796 return (-1);
16797 /* TODO: assign user data. */
16798 ctxt->pctxt->error = ctxt->error;
16799 ctxt->pctxt->warning = ctxt->warning;
16800 ctxt->xsiAssemble = 1;
16801 } else
16802 ctxt->xsiAssemble = 0;
16803 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16804 * ctxt->xsiAssemble = 1;
16805 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016806 /*
16807 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016808 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016809 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016810 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16811 if (ret == -1) {
16812 xmlSchemaVCustomErr(ctxt,
16813 XML_SCHEMAV_INTERNAL,
16814 ctxt->node, NULL,
16815 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016816 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016817 }
16818 /*
16819 * NOTE: We won't react on schema parser errors here.
16820 * TODO: But a warning would be nice.
16821 */
16822 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016823 if (ret != -1) {
16824 if (ctxt->node->ns != NULL)
16825 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16826 ctxt->node->ns->href);
16827 else
16828 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16829
16830 if (elemDecl == NULL) {
16831 xmlSchemaVCustomErr(ctxt,
16832 XML_SCHEMAV_CVC_ELT_1,
16833 ctxt->node, NULL,
16834 "No matching global declaration available", NULL);
16835 ret = XML_SCHEMAV_CVC_ELT_1;
16836 } else {
16837 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16838 if (ret < 0) {
16839 xmlSchemaVCustomErr(ctxt,
16840 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16841 "Internal error: xmlSchemaValidateElement, "
16842 "calling validation by declaration", NULL);
16843 }
16844 }
16845 }
16846 /* ctxt->xsiAssemble = 0; */
16847 if (ctxt->xsiAssemble) {
16848 if (ctxt->schema != NULL) {
16849 xmlSchemaFree(ctxt->schema);
16850 ctxt->schema = NULL;
16851 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016852 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016853 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016854}
16855
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016856
Daniel Veillard4255d502002-04-16 15:50:10 +000016857/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016858 * xmlSchemaValidateOneElement:
16859 * @ctxt: a schema validation context
16860 * @elem: an element node
16861 *
16862 * Validate a branch of a tree, starting with the given @elem.
16863 *
16864 * Returns 0 if the element and its subtree is valid, a positive error
16865 * code number otherwise and -1 in case of an internal or API error.
16866 */
16867int
16868xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16869{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016870 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016871 return (-1);
16872
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016873 if (ctxt->schema == NULL) {
16874 xmlSchemaVErr(ctxt, NULL,
16875 XML_SCHEMAV_INTERNAL,
16876 "API error: xmlSchemaValidateOneElement, "
16877 "no schema specified.\n", NULL, NULL);
16878 return (-1);
16879 }
16880
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016881 ctxt->doc = elem->doc;
16882 ctxt->err = 0;
16883 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016884 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016885 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016886 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016887}
16888
16889/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016890 * xmlSchemaValidateDocument:
16891 * @ctxt: a schema validation context
16892 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016893 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016894 *
16895 * Validate a document tree in memory.
16896 *
16897 * Returns 0 if the document is schemas valid, a positive error code
16898 * number otherwise and -1 in case of internal or API error.
16899 */
16900static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016901xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16902{
Daniel Veillard4255d502002-04-16 15:50:10 +000016903 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016904
Daniel Veillard4255d502002-04-16 15:50:10 +000016905 root = xmlDocGetRootElement(doc);
16906 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016907 xmlSchemaVCustomErr(ctxt,
16908 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16909 (xmlNodePtr) doc, NULL,
16910 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016911 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016912 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016913 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016914 /*
16915 * Okay, start the recursive validation
16916 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016917 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016918 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016919 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016920
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016921 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016922}
16923
16924/************************************************************************
16925 * *
16926 * SAX Validation code *
16927 * *
16928 ************************************************************************/
16929
16930/************************************************************************
16931 * *
16932 * Validation interfaces *
16933 * *
16934 ************************************************************************/
16935
16936/**
16937 * xmlSchemaNewValidCtxt:
16938 * @schema: a precompiled XML Schemas
16939 *
16940 * Create an XML Schemas validation context based on the given schema
16941 *
16942 * Returns the validation context or NULL in case of error
16943 */
16944xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016945xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16946{
Daniel Veillard4255d502002-04-16 15:50:10 +000016947 xmlSchemaValidCtxtPtr ret;
16948
16949 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16950 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016951 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016952 return (NULL);
16953 }
16954 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016955 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016956 ret->attrTop = NULL;
16957 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016958 return (ret);
16959}
16960
16961/**
16962 * xmlSchemaFreeValidCtxt:
16963 * @ctxt: the schema validation context
16964 *
16965 * Free the resources associated to the schema validation context
16966 */
16967void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016968xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16969{
Daniel Veillard4255d502002-04-16 15:50:10 +000016970 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016971 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016972 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016973 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016974 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016975 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016976 if (ctxt->pctxt != NULL) {
16977 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16978 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016979 xmlFree(ctxt);
16980}
16981
16982/**
16983 * xmlSchemaSetValidErrors:
16984 * @ctxt: a schema validation context
16985 * @err: the error function
16986 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016987 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016988 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016989 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016990 */
16991void
16992xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016993 xmlSchemaValidityErrorFunc err,
16994 xmlSchemaValidityWarningFunc warn, void *ctx)
16995{
Daniel Veillard4255d502002-04-16 15:50:10 +000016996 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016997 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016998 ctxt->error = err;
16999 ctxt->warning = warn;
17000 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017001 if (ctxt->pctxt != NULL)
17002 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000017003}
17004
17005/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017006 * xmlSchemaGetValidErrors:
17007 * @ctxt: a XML-Schema validation context
17008 * @err: the error function result
17009 * @warn: the warning function result
17010 * @ctx: the functions context result
17011 *
17012 * Get the error and warning callback informations
17013 *
17014 * Returns -1 in case of error and 0 otherwise
17015 */
17016int
17017xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
17018 xmlSchemaValidityErrorFunc * err,
17019 xmlSchemaValidityWarningFunc * warn, void **ctx)
17020{
17021 if (ctxt == NULL)
17022 return (-1);
17023 if (err != NULL)
17024 *err = ctxt->error;
17025 if (warn != NULL)
17026 *warn = ctxt->warning;
17027 if (ctx != NULL)
17028 *ctx = ctxt->userData;
17029 return (0);
17030}
17031
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017032
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017033/**
Daniel Veillard6927b102004-10-27 17:29:04 +000017034 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017035 * @ctxt: a schema validation context
17036 * @options: a combination of xmlSchemaValidOption
17037 *
17038 * Sets the options to be used during the validation.
17039 *
17040 * Returns 0 in case of success, -1 in case of an
17041 * API error.
17042 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017043int
17044xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
17045 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017046
17047{
17048 int i;
17049
17050 if (ctxt == NULL)
17051 return (-1);
17052 /*
17053 * WARNING: Change the start value if adding to the
17054 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017055 * TODO: Is there an other, more easy to maintain,
17056 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017057 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017058 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017059 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017060 xmlSchemaVErr(ctxt, NULL,
17061 XML_SCHEMAV_INTERNAL,
17062 "Internal error: xmlSchemaSetValidOptions, "
17063 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017064 return (-1);
17065 }
17066 }
17067 ctxt->options = options;
17068 return (0);
17069}
17070
17071/**
Daniel Veillard6927b102004-10-27 17:29:04 +000017072 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017073 * @ctxt: a schema validation context
17074 *
William M. Brack21e4ef22005-01-02 09:53:13 +000017075 * Get the validation context options.
17076 *
17077 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017078 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017079int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017080xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
17081
17082{
17083 if (ctxt == NULL)
17084 return (-1);
17085 else
17086 return (ctxt->options);
17087}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017088
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017089
Daniel Veillard259f0df2004-08-18 09:13:18 +000017090/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017091 * xmlSchemaValidateDoc:
17092 * @ctxt: a schema validation context
17093 * @doc: a parsed document tree
17094 *
17095 * Validate a document tree in memory.
17096 *
17097 * Returns 0 if the document is schemas valid, a positive error code
17098 * number otherwise and -1 in case of internal or API error.
17099 */
17100int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017101xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
17102{
Daniel Veillard4255d502002-04-16 15:50:10 +000017103 int ret;
17104
17105 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017106 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017107
17108 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000017109 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017110 ctxt->nberrors = 0;
17111
17112 /*
17113 if (ctxt->schema == NULL) {
17114 xmlSchemaVErr(ctxt, NULL,
17115 XML_SCHEMAV_INTERNAL,
17116 "API error: xmlSchemaValidateDoc, "
17117 "no schema specified and assembling of schemata "
17118 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
17119 "is not enabled.\n", NULL, NULL);
17120 return (-1);
17121 }
17122 */
Daniel Veillard4255d502002-04-16 15:50:10 +000017123 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017124 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000017125}
17126
17127/**
17128 * xmlSchemaValidateStream:
17129 * @ctxt: a schema validation context
17130 * @input: the input to use for reading the data
17131 * @enc: an optional encoding information
17132 * @sax: a SAX handler for the resulting events
17133 * @user_data: the context to provide to the SAX handler.
17134 *
17135 * Validate a document tree in memory.
17136 *
17137 * Returns 0 if the document is schemas valid, a positive error code
17138 * number otherwise and -1 in case of internal or API error.
17139 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017140int
Daniel Veillard4255d502002-04-16 15:50:10 +000017141xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017142 xmlParserInputBufferPtr input, xmlCharEncoding enc,
17143 xmlSAXHandlerPtr sax, void *user_data)
17144{
Daniel Veillard4255d502002-04-16 15:50:10 +000017145 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017146 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017147 ctxt->input = input;
17148 ctxt->enc = enc;
17149 ctxt->sax = sax;
17150 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017151 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017152}
17153
17154#endif /* LIBXML_SCHEMAS_ENABLED */