blob: d7fa515abd03d160a59a95a846fd5c2398655cc0 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000037
Daniel Veillarda84c0b32003-06-02 16:58:46 +000038/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000039
Daniel Veillard82bbbd42003-05-11 20:16:09 +000040/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000041
Daniel Veillard82bbbd42003-05-11 20:16:09 +000042/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000043
Daniel Veillard118aed72002-09-24 14:13:13 +000044/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000045
Daniel Veillard4255d502002-04-16 15:50:10 +000046/* #define DEBUG_AUTOMATA 1 */
47
Daniel Veillard3646d642004-06-02 19:19:14 +000048/* #define DEBUG_ATTR_VALIDATION 1 */
49
Daniel Veillardc0826a72004-08-10 14:17:33 +000050/* #define DEBUG_UNION_VALIDATION 1 */
51
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define UNBOUNDED (1 << 30)
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
William M. Brack2f2a6632004-08-20 23:09:47 +000059#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000060
Daniel Veillard4255d502002-04-16 15:50:10 +000061/*
62 * The XML Schemas namespaces
63 */
64static const xmlChar *xmlSchemaNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema";
66
67static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
68 "http://www.w3.org/2001/XMLSchema-instance";
69
Daniel Veillardc0826a72004-08-10 14:17:33 +000070static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
71 "Element decl.";
72static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
73 "Element ref.";
74static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
75 "Attribute decl.";
76static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
77 "Attribute ref.";
78static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
79 "ST";
80static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
81 "CT";
82
Daniel Veillard4255d502002-04-16 15:50:10 +000083#define IS_SCHEMA(node, type) \
84 ((node != NULL) && (node->ns != NULL) && \
85 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
86 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
87
Daniel Veillardc0826a72004-08-10 14:17:33 +000088#define FREE_AND_NULL(str) \
89 if (str != NULL) { \
90 xmlFree(str); \
91 str = NULL; \
92 }
93
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000094#define IS_ANYTYPE(item) \
95 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
96 (item->builtInType == XML_SCHEMAS_ANYTYPE))
97
98#define IS_COMPLEX_TYPE(item) \
99 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
100 (item->builtInType == XML_SCHEMAS_ANYTYPE))
101
102#define IS_SIMPLE_TYPE(item) \
103 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
104 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
105 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
106
Daniel Veillardc0826a72004-08-10 14:17:33 +0000107#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
108#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
109#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define XML_SCHEMAS_PARSE_ERROR 1
112
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000113#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000115
116/*
117* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
118* allow to assemble schemata with
119* the same target namespace from
120* different sources; otherwise, the first
121* encountered schema with a specific target
122* namespace will be used only *
123
124*
125* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
126* locate schemata to be imported
127* using the namespace name; otherwise
128* the location URI will be used */
129
130/*
131* xmlSchemaParserOption:
132*
133* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000135typedef enum {
136 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000137 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000138 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000139 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000140} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000141*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000142
143/*
144XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000145 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
146 int options);
147XMLPUBFUN int XMLCALL
148 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
149
150*/
151
152typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
153typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
154struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000155 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156 int nbItems; /* used for dynamic addition of schemata */
157 int sizeItems; /* used for dynamic addition of schemata */
158};
159
Daniel Veillard4255d502002-04-16 15:50:10 +0000160struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000161 void *userData; /* user specific data block */
162 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
163 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000164 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000165 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000166 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000167
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000168 xmlSchemaPtr topschema; /* The main schema */
169 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
170
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000171 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000172 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000173 int counter;
174
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000175 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000177 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000178
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179 const char *buffer;
180 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000181
Daniel Veillard4255d502002-04-16 15:50:10 +0000182 /*
183 * Used to build complex element content models
184 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000185 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 xmlAutomataStatePtr start;
187 xmlAutomataStatePtr end;
188 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000189
190 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000191 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000192 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
193 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194 xmlSchemaAssemblePtr assemble;
195 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000196 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000197};
198
199
200#define XML_SCHEMAS_ATTR_UNKNOWN 1
201#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000202#define XML_SCHEMAS_ATTR_PROHIBITED 3
203#define XML_SCHEMAS_ATTR_MISSING 4
204#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
205#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000206#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
207#define XML_SCHEMAS_ATTR_DEFAULT 8
Daniel Veillard4255d502002-04-16 15:50:10 +0000208
209typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
210typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
211struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000212 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000213 xmlAttrPtr attr;
214 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000215 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000216 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000217};
218
219/**
220 * xmlSchemaValidCtxt:
221 *
222 * A Schemas validation context
223 */
224
225struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *userData; /* user specific data block */
227 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
228 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000229 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000230
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000231 xmlSchemaPtr schema; /* The schema in use */
232 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlCharEncoding enc;
235 xmlSAXHandlerPtr sax;
236 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 xmlDocPtr myDoc;
239 int err;
240 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000241
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000242 xmlNodePtr node;
243 xmlNodePtr cur;
244 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000246 xmlRegExecCtxtPtr regexp;
247 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248
Daniel Veillard3646d642004-06-02 19:19:14 +0000249 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000250 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000251 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000252 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlNodePtr validationRoot;
255 xmlSchemaParserCtxtPtr pctxt;
256 int xsiAssemble;
Daniel Veillard4255d502002-04-16 15:50:10 +0000257};
258
Daniel Veillard1d913862003-11-21 00:28:39 +0000259/*
260 * These are the entries in the schemas importSchemas hash table
261 */
262typedef struct _xmlSchemaImport xmlSchemaImport;
263typedef xmlSchemaImport *xmlSchemaImportPtr;
264struct _xmlSchemaImport {
265 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000266 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000267 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000268 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000269};
Daniel Veillard4255d502002-04-16 15:50:10 +0000270
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000271/*
272 * These are the entries associated to includes in a schemas
273 */
274typedef struct _xmlSchemaInclude xmlSchemaInclude;
275typedef xmlSchemaInclude *xmlSchemaIncludePtr;
276struct _xmlSchemaInclude {
277 xmlSchemaIncludePtr next;
278
279 const xmlChar *schemaLocation;
280 xmlDocPtr doc;
281};
282
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000283typedef struct _xmlSchemaParticle xmlSchemaParticle;
284typedef xmlSchemaParticle *xmlSchemaParticlePtr;
285struct _xmlSchemaParticle {
286 xmlSchemaTypeType type;
287 xmlSchemaParticlePtr next; /* the next particle if in a list */
288 int minOccurs;
289 int maxOccurs;
290 xmlSchemaTypePtr term;
291};
292
293
294typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
295typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
296struct _xmlSchemaModelGroup {
297 xmlSchemaTypeType type;
298 int compositor; /* one of all, choice or sequence */
299 xmlSchemaParticlePtr particles; /* list of particles */
300 xmlSchemaAnnotPtr annot;
301};
302
303typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
304typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
305struct _xmlSchemaModelGroupDef {
306 xmlSchemaTypeType type;
307 const xmlChar *name;
308 const xmlChar *targetNamespace;
309 xmlSchemaModelGroupPtr modelGroup;
310 xmlSchemaAnnotPtr annot;
311};
312
Daniel Veillard4255d502002-04-16 15:50:10 +0000313/************************************************************************
314 * *
315 * Some predeclarations *
316 * *
317 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000319static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
320 xmlSchemaPtr schema,
321 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000322static void
323xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
324 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
325static const char *
326xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
327static int
328xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000329 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000330 const xmlChar *value,
331 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000332 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000333 int normalize,
334 int checkNodes);
335static int
336xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
337 xmlSchemaElementPtr elemDecl);
338static int
339xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
340 xmlSchemaTypePtr type);
341static int
342xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000343static int
344xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
345 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000346
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000347/************************************************************************
348 * *
349 * Datatype error handlers *
350 * *
351 ************************************************************************/
352
353/**
354 * xmlSchemaPErrMemory:
355 * @node: a context node
356 * @extra: extra informations
357 *
358 * Handle an out of memory condition
359 */
360static void
361xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
362 const char *extra, xmlNodePtr node)
363{
364 if (ctxt != NULL)
365 ctxt->nberrors++;
366 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
367 extra);
368}
369
370/**
371 * xmlSchemaPErr:
372 * @ctxt: the parsing context
373 * @node: the context node
374 * @error: the error code
375 * @msg: the error message
376 * @str1: extra data
377 * @str2: extra data
378 *
379 * Handle a parser error
380 */
381static void
382xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
383 const char *msg, const xmlChar * str1, const xmlChar * str2)
384{
385 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000386 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000387 void *data = NULL;
388
389 if (ctxt != NULL) {
390 ctxt->nberrors++;
391 channel = ctxt->error;
392 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000393 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000394 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000395 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000396 error, XML_ERR_ERROR, NULL, 0,
397 (const char *) str1, (const char *) str2, NULL, 0, 0,
398 msg, str1, str2);
399}
400
401/**
402 * xmlSchemaPErr2:
403 * @ctxt: the parsing context
404 * @node: the context node
405 * @node: the current child
406 * @error: the error code
407 * @msg: the error message
408 * @str1: extra data
409 * @str2: extra data
410 *
411 * Handle a parser error
412 */
413static void
414xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
415 xmlNodePtr child, int error,
416 const char *msg, const xmlChar * str1, const xmlChar * str2)
417{
418 if (child != NULL)
419 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
420 else
421 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
422}
423
Daniel Veillard01fa6152004-06-29 17:04:39 +0000424
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000425/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000426 * xmlSchemaPErrExt:
427 * @ctxt: the parsing context
428 * @node: the context node
429 * @error: the error code
430 * @strData1: extra data
431 * @strData2: extra data
432 * @strData3: extra data
433 * @msg: the message
434 * @str1: extra parameter for the message display
435 * @str2: extra parameter for the message display
436 * @str3: extra parameter for the message display
437 * @str4: extra parameter for the message display
438 * @str5: extra parameter for the message display
439 *
440 * Handle a parser error
441 */
442static void
443xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
444 const xmlChar * strData1, const xmlChar * strData2,
445 const xmlChar * strData3, const char *msg, const xmlChar * str1,
446 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
447 const xmlChar * str5)
448{
449
450 xmlGenericErrorFunc channel = NULL;
451 xmlStructuredErrorFunc schannel = NULL;
452 void *data = NULL;
453
454 if (ctxt != NULL) {
455 ctxt->nberrors++;
456 channel = ctxt->error;
457 data = ctxt->userData;
458 schannel = ctxt->serror;
459 }
460 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
461 error, XML_ERR_ERROR, NULL, 0,
462 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000463 (const char *) strData3, 0, 0, msg, str1, str2,
464 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000465}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000466
Daniel Veillard3646d642004-06-02 19:19:14 +0000467
468/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000469 * xmlSchemaVTypeErrMemory:
470 * @node: a context node
471 * @extra: extra informations
472 *
473 * Handle an out of memory condition
474 */
475static void
476xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
477 const char *extra, xmlNodePtr node)
478{
479 if (ctxt != NULL) {
480 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000481 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000482 }
483 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
484 extra);
485}
486
487/**
488 * xmlSchemaVErr3:
489 * @ctxt: the validation context
490 * @node: the context node
491 * @error: the error code
492 * @msg: the error message
493 * @str1: extra data
494 * @str2: extra data
495 * @str3: extra data
496 *
497 * Handle a validation error
498 */
499static void
500xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
501 const char *msg, const xmlChar *str1, const xmlChar *str2,
502 const xmlChar *str3)
503{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000504 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000505 xmlGenericErrorFunc channel = NULL;
506 void *data = NULL;
507
508 if (ctxt != NULL) {
509 ctxt->nberrors++;
510 ctxt->err = error;
511 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000512 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000513 data = ctxt->userData;
514 }
515 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000516 /* Removed, since the old schema error codes have been
517 * substituted for the global error codes.
518 *
519 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
520 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000521 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000522 error, XML_ERR_ERROR, NULL, 0,
523 (const char *) str1, (const char *) str2,
524 (const char *) str3, 0, 0,
525 msg, str1, str2, str3);
526}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000527
528/**
529 * xmlSchemaVErrExt:
530 * @ctxt: the validation context
531 * @node: the context node
532 * @error: the error code
533 * @msg: the message
534 * @str1: extra parameter for the message display
535 * @str2: extra parameter for the message display
536 * @str3: extra parameter for the message display
537 * @str4: extra parameter for the message display
538 * @str5: extra parameter for the message display
539 *
540 * Handle a validation error
541 */
542static void
543xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
544 const char *msg, const xmlChar * str1,
545 const xmlChar * str2, const xmlChar * str3,
546 const xmlChar * str4, const xmlChar * str5)
547{
548 xmlStructuredErrorFunc schannel = NULL;
549 xmlGenericErrorFunc channel = NULL;
550 void *data = NULL;
551
552 if (ctxt != NULL) {
553 ctxt->nberrors++;
554 ctxt->err = error;
555 channel = ctxt->error;
556 schannel = ctxt->serror;
557 data = ctxt->userData;
558 }
559 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000560 /* Removed, since the old schema error codes have been
561 * substituted for the global error codes.
562 *
563 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
564 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000565 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
566 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
567 msg, str1, str2, str3, str4, str5);
568}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000569/**
570 * xmlSchemaVErr:
571 * @ctxt: the validation context
572 * @node: the context node
573 * @error: the error code
574 * @msg: the error message
575 * @str1: extra data
576 * @str2: extra data
577 *
578 * Handle a validation error
579 */
580static void
581xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
582 const char *msg, const xmlChar * str1, const xmlChar * str2)
583{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000584 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000585 xmlGenericErrorFunc channel = NULL;
586 void *data = NULL;
587
588 if (ctxt != NULL) {
589 ctxt->nberrors++;
590 ctxt->err = error;
591 channel = ctxt->error;
592 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000593 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000594 }
595 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000596 /* Removed, since the old schema error codes have been
597 * substituted for the global error codes.
598 *
599 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
600 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000601 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000602 error, XML_ERR_ERROR, NULL, 0,
603 (const char *) str1, (const char *) str2, NULL, 0, 0,
604 msg, str1, str2);
605}
Daniel Veillard4255d502002-04-16 15:50:10 +0000606
Daniel Veillardc0826a72004-08-10 14:17:33 +0000607/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000608 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000609 * @attr: the attribute declaration/use
610 *
611 * Returns the name of the attribute; if the attribute
612 * is a reference, the name of the referenced global type will be returned.
613 */
614static const xmlChar *
615xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
616{
617 if (attr->ref != NULL)
618 return(attr->ref);
619 else
620 return(attr->name);
621}
622
623/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000624 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000625 * @type: the type (element or attribute)
626 *
627 * Returns the target namespace URI of the type; if the type is a reference,
628 * the target namespace of the referenced type will be returned.
629 */
630static const xmlChar *
631xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
632{
633 if (attr->ref != NULL)
634 return (attr->refNs);
635 else
636 return(attr->targetNamespace);
637}
638
639/**
640 * xmlSchemaFormatNsUriLocal:
641 * @buf: the string buffer
642 * @uri: the namespace URI
643 * @local: the local name
644 *
645 * Returns a representation of the given URI used
646 * for error reports.
647 *
648 * Returns an empty string, if @ns is NULL, a formatted
649 * string otherwise.
650 */
651static const xmlChar*
652xmlSchemaFormatNsUriLocal(xmlChar **buf,
653 const xmlChar *uri, const xmlChar *local)
654{
655 if (*buf != NULL)
656 xmlFree(*buf);
657 if (uri == NULL) {
658 *buf = xmlStrdup(BAD_CAST "{'");
659 *buf = xmlStrcat(*buf, local);
660 } else {
661 *buf = xmlStrdup(BAD_CAST "{'");
662 *buf = xmlStrcat(*buf, uri);
663 *buf = xmlStrcat(*buf, BAD_CAST "', '");
664 *buf = xmlStrcat(*buf, local);
665 }
666 *buf = xmlStrcat(*buf, BAD_CAST "'}");
667 return ((const xmlChar *) *buf);
668}
669
670/**
671 * xmlSchemaFormatNsPrefixLocal:
672 * @buf: the string buffer
673 * @ns: the namespace
674 * @local: the local name
675 *
676 * Returns a representation of the given URI used
677 * for error reports.
678 *
679 * Returns an empty string, if @ns is NULL, a formatted
680 * string otherwise.
681 */
682static const xmlChar*
683xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
684 xmlNsPtr ns, const xmlChar *local)
685{
686 if (*buf != NULL) {
687 xmlFree(*buf);
688 *buf = NULL;
689 }
690 if ((ns == NULL) || (ns->prefix == NULL))
691 return(local);
692 else {
693 *buf = xmlStrdup(ns->prefix);
694 *buf = xmlStrcat(*buf, BAD_CAST ":");
695 *buf = xmlStrcat(*buf, local);
696 }
697 return ((const xmlChar *) *buf);
698}
699
700/**
701 * xmlSchemaFormatItemForReport:
702 * @buf: the string buffer
703 * @itemDes: the designation of the item
704 * @itemName: the name of the item
705 * @item: the item as an object
706 * @itemNode: the node of the item
707 * @local: the local name
708 * @parsing: if the function is used during the parse
709 *
710 * Returns a representation of the given item used
711 * for error reports.
712 *
713 * The following order is used to build the resulting
714 * designation if the arguments are not NULL:
715 * 1a. If itemDes not NULL -> itemDes
716 * 1b. If (itemDes not NULL) and (itemName not NULL)
717 * -> itemDes + itemName
718 * 2. If the preceding was NULL and (item not NULL) -> item
719 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
720 *
721 * If the itemNode is an attribute node, the name of the attribute
722 * will be appended to the result.
723 *
724 * Returns the formatted string and sets @buf to the resulting value.
725 */
726static xmlChar*
727xmlSchemaFormatItemForReport(xmlChar **buf,
728 const xmlChar *itemDes,
729 xmlSchemaTypePtr item,
730 xmlNodePtr itemNode,
731 int parsing)
732{
733 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000734 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000735
736 if (*buf != NULL) {
737 xmlFree(*buf);
738 *buf = NULL;
739 }
740
William M. Brack2f2a6632004-08-20 23:09:47 +0000741 if (itemDes != NULL) {
742 *buf = xmlStrdup(itemDes);
743 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000744 if (item->type == XML_SCHEMA_TYPE_BASIC) {
745 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
746 *buf = xmlStrdup(BAD_CAST "'anyType'");
747 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
748 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
749 else {
750 /* *buf = xmlStrdup(BAD_CAST "bi "); */
751 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
752 *buf = xmlStrdup(BAD_CAST "'");
753 *buf = xmlStrcat(*buf, item->name);
754 *buf = xmlStrcat(*buf, BAD_CAST "'");
755 }
756 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
757 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
758 *buf = xmlStrdup(xmlSchemaElemDesST);
759 *buf = xmlStrcat(*buf, BAD_CAST " '");
760 *buf = xmlStrcat(*buf, item->name);
761 *buf = xmlStrcat(*buf, BAD_CAST "'");
762 } else {
763 *buf = xmlStrdup(xmlSchemaElemDesST);
764 *buf = xmlStrcat(*buf, BAD_CAST " local");
765 }
766 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
767 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
768 *buf = xmlStrdup(xmlSchemaElemDesCT);
769 *buf = xmlStrcat(*buf, BAD_CAST " '");
770 *buf = xmlStrcat(*buf, item->name);
771 *buf = xmlStrcat(*buf, BAD_CAST "'");
772 } else {
773 *buf = xmlStrdup(xmlSchemaElemDesCT);
774 *buf = xmlStrcat(*buf, BAD_CAST " local");
775 }
776 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
777 xmlSchemaAttributePtr attr;
778
779 attr = (xmlSchemaAttributePtr) item;
780 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
781 (attr->ref == NULL)) {
782 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
783 *buf = xmlStrcat(*buf, BAD_CAST " '");
784 *buf = xmlStrcat(*buf, attr->name);
785 *buf = xmlStrcat(*buf, BAD_CAST "'");
786 } else {
787 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
788 *buf = xmlStrcat(*buf, BAD_CAST " '");
789 *buf = xmlStrcat(*buf, attr->refPrefix);
790 *buf = xmlStrcat(*buf, BAD_CAST ":");
791 *buf = xmlStrcat(*buf, attr->ref);
792 *buf = xmlStrcat(*buf, BAD_CAST "'");
793 }
794 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
795 xmlSchemaElementPtr elem;
796
797 elem = (xmlSchemaElementPtr) item;
798 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
799 (elem->ref == NULL)) {
800 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
801 *buf = xmlStrcat(*buf, BAD_CAST " '");
802 *buf = xmlStrcat(*buf, elem->name);
803 *buf = xmlStrcat(*buf, BAD_CAST "'");
804 } else {
805 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
806 *buf = xmlStrcat(*buf, BAD_CAST " '");
807 *buf = xmlStrcat(*buf, elem->refPrefix);
808 *buf = xmlStrcat(*buf, BAD_CAST ":");
809 *buf = xmlStrcat(*buf, elem->ref);
810 *buf = xmlStrcat(*buf, BAD_CAST "'");
811 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000812 } else
813 named = 0;
814 } else
815 named = 0;
816
817 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000818 xmlNodePtr elem;
819
820 if (itemNode->type == XML_ATTRIBUTE_NODE)
821 elem = itemNode->parent;
822 else
823 elem = itemNode;
824 *buf = xmlStrdup(BAD_CAST "Element '");
825 if (parsing)
826 *buf = xmlStrcat(*buf, elem->name);
827 else
828 *buf = xmlStrcat(*buf,
829 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
830 *buf = xmlStrcat(*buf, BAD_CAST "'");
831 }
832 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
833 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
834 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
835 itemNode->ns, itemNode->name));
836 *buf = xmlStrcat(*buf, BAD_CAST "'");
837 }
838 FREE_AND_NULL(str);
839
840 return (*buf);
841}
842
843/**
844 * xmlSchemaPFormatItemDes:
845 * @buf: the string buffer
846 * @item: the item as a schema object
847 * @itemNode: the item as a node
848 *
849 * If the pointer to @buf is not NULL and @but holds no value,
850 * the value is set to a item designation using
851 * xmlSchemaFormatItemForReport. This one avoids adding
852 * an attribute designation postfix.
853 *
854 * Returns a string of all enumeration elements.
855 */
856static void
857xmlSchemaPRequestItemDes(xmlChar **buf,
858 xmlSchemaTypePtr item,
859 xmlNodePtr itemNode)
860{
861 if ((buf == 0) || (*buf != NULL))
862 return;
863 if (itemNode->type == XML_ATTRIBUTE_NODE)
864 itemNode = itemNode->parent;
865 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
866}
867
868/**
869 * xmlSchemaFormatFacetEnumSet:
870 * @buf: the string buffer
871 * @type: the type holding the enumeration facets
872 *
873 * Builds a string consisting of all enumeration elements.
874 *
875 * Returns a string of all enumeration elements.
876 */
877static const xmlChar *
878xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
879{
880 xmlSchemaFacetLinkPtr link;
881
882 if (*buf != NULL)
883 xmlFree(*buf);
884 *buf = NULL;
885 for (link = type->facetSet; link != NULL; link = link->next) {
886 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
887 if (*buf == NULL) {
888 *buf = xmlStrdup(BAD_CAST "'");
889 *buf = xmlStrcat(*buf, link->facet->value);
890 *buf = xmlStrcat(*buf, BAD_CAST "'");
891 } else {
892 *buf = xmlStrcat(*buf, BAD_CAST ", '");
893 *buf = xmlStrcat(*buf, link->facet->value);
894 *buf = xmlStrcat(*buf, BAD_CAST "'");
895 }
896 }
897 }
898 return ((const xmlChar *) *buf);
899}
900
901/**
902 * xmlSchemaVFacetErr:
903 * @ctxt: the schema validation context
904 * @error: the error code
905 * @node: the node to be validated
906 * @value: the value of the node
907 * @type: the type holding the facet
908 * @facet: the facet
909 * @message: the error message of NULL
910 * @str1: extra data
911 * @str2: extra data
912 * @str3: extra data
913 *
914 * Reports a facet validation error.
915 * TODO: Should this report the value of an element as well?
916 */
917static void
918xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
919 xmlParserErrors error,
920 xmlNodePtr node,
921 const xmlChar *value,
922 unsigned long length,
923 xmlSchemaTypePtr type,
924 xmlSchemaFacetPtr facet,
925 const char *message,
926 const xmlChar *str1,
927 const xmlChar *str2,
928 const xmlChar *str3)
929{
930 xmlChar *str = NULL, *msg = NULL;
931 xmlSchemaTypeType facetType;
932
933 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
934 msg = xmlStrcat(msg, BAD_CAST " [");
935 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
936 msg = xmlStrcat(msg, BAD_CAST ", facet '");
937 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
938 facetType = XML_SCHEMA_FACET_ENUMERATION;
939 /*
940 * If enumerations are validated, one must not expect the
941 * facet to be given.
942 */
943 } else
944 facetType = facet->type;
945 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
946 msg = xmlStrcat(msg, BAD_CAST "']: ");
947 if (message == NULL) {
948 /*
949 * Use a default message.
950 */
951 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
952 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
953 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
954
955 char len[25], actLen[25];
956
957 /* FIXME, TODO: What is the max expected string length of the
958 * this value?
959 */
960 if (node->type == XML_ATTRIBUTE_NODE)
961 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
962 else
963 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
964
965 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
966 snprintf(actLen, 24, "%lu", length);
967
968 if (facetType == XML_SCHEMA_FACET_LENGTH)
969 msg = xmlStrcat(msg,
970 BAD_CAST "this differs from the allowed length of '%s'.\n");
971 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
972 msg = xmlStrcat(msg,
973 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
974 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
975 msg = xmlStrcat(msg,
976 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
977
978 if (node->type == XML_ATTRIBUTE_NODE)
979 xmlSchemaVErrExt(ctxt, node, error,
980 (const char *) msg,
981 value, (const xmlChar *) actLen, (const xmlChar *) len,
982 NULL, NULL);
983 else
984 xmlSchemaVErr(ctxt, node, error,
985 (const char *) msg,
986 (const xmlChar *) actLen, (const xmlChar *) len);
987
988 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
989 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
990 "of the set {%s}.\n");
991 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
992 xmlSchemaFormatFacetEnumSet(&str, type));
993 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
994 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
995 "by the pattern '%s'.\n");
996 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
997 facet->value);
998 } else if (node->type == XML_ATTRIBUTE_NODE) {
999 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1000 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1001 } else {
1002 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1003 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1004 }
1005 } else {
1006 msg = xmlStrcat(msg, (const xmlChar *) message);
1007 msg = xmlStrcat(msg, BAD_CAST ".\n");
1008 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1009 }
1010 FREE_AND_NULL(str)
1011 xmlFree(msg);
1012}
1013
1014/**
1015 * xmlSchemaVSimpleTypeErr:
1016 * @ctxt: the schema validation context
1017 * @error: the error code
1018 * @type: the type used for validation
1019 * @node: the node containing the validated value
1020 * @value: the validated value
1021 *
1022 * Reports a simple type validation error.
1023 * TODO: Should this report the value of an element as well?
1024 */
1025static void
1026xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1027 xmlParserErrors error,
1028 xmlNodePtr node,
1029 const xmlChar *value,
1030 xmlSchemaTypePtr type)
1031{
1032 xmlChar *str = NULL, *msg = NULL;
1033
1034 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1035 msg = xmlStrcat(msg, BAD_CAST " [");
1036 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1037 if (node->type == XML_ATTRIBUTE_NODE) {
1038 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1039 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1040 } else {
1041 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1042 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1043 }
1044 FREE_AND_NULL(str)
1045 xmlFree(msg);
1046}
1047
1048/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001049 * xmlSchemaVComplexTypeErr:
1050 * @ctxt: the schema validation context
1051 * @error: the error code
1052 * @node: the node containing the validated value
1053 * @type: the complex type used for validation
1054 * @message: the error message
1055 *
1056 * Reports a complex type validation error.
1057 */
1058static void
1059xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1060 xmlParserErrors error,
1061 xmlNodePtr node,
1062 xmlSchemaTypePtr type,
1063 const char *message)
1064{
1065 xmlChar *str = NULL, *msg = NULL;
1066
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001067 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1068 if (type != NULL) {
1069 msg = xmlStrcat(msg, BAD_CAST " [");
1070 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1071 msg = xmlStrcat(msg, BAD_CAST "]");
1072 }
1073 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
William M. Brack2f2a6632004-08-20 23:09:47 +00001074 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
1075 (const xmlChar *) message, NULL);
1076 FREE_AND_NULL(str)
1077 xmlFree(msg);
1078}
1079
1080/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001081 * xmlSchemaPMissingAttrErr:
1082 * @ctxt: the schema validation context
1083 * @ownerDes: the designation of the owner
1084 * @ownerName: the name of the owner
1085 * @ownerItem: the owner as a schema object
1086 * @ownerElem: the owner as an element node
1087 * @node: the parent element node of the missing attribute node
1088 * @type: the corresponding type of the attribute node
1089 *
1090 * Reports an illegal attribute.
1091 */
1092static void
1093xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1094 xmlParserErrors error,
1095 xmlChar **ownerDes,
1096 xmlSchemaTypePtr ownerItem,
1097 xmlNodePtr ownerElem,
1098 const char *name,
1099 const char *message)
1100{
1101 xmlChar *des = NULL;
1102
1103 if (ownerDes == NULL)
1104 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1105 else if (*ownerDes == NULL) {
1106 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1107 des = *ownerDes;
1108 } else
1109 des = *ownerDes;
1110 if (message != NULL)
1111 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1112 else
1113 xmlSchemaPErr(ctxt, ownerElem, error,
1114 "%s: The attribute '%s' is required but missing.\n",
1115 BAD_CAST des, BAD_CAST name);
1116 if (ownerDes == NULL)
1117 FREE_AND_NULL(des);
1118}
1119
William M. Brack2f2a6632004-08-20 23:09:47 +00001120/**
1121 * xmlSchemaCompTypeToString:
1122 * @type: the type of the schema item
1123 *
1124 * Returns the component name of a schema item.
1125 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001126static const char *
1127xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1128{
1129 switch (type) {
1130 case XML_SCHEMA_TYPE_SIMPLE:
1131 return("simple type definition");
1132 case XML_SCHEMA_TYPE_COMPLEX:
1133 return("complex type definition");
1134 case XML_SCHEMA_TYPE_ELEMENT:
1135 return("element declaration");
1136 case XML_SCHEMA_TYPE_ATTRIBUTE:
1137 return("attribute declaration");
1138 case XML_SCHEMA_TYPE_GROUP:
1139 return("model group definition");
1140 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1141 return("attribute group definition");
1142 case XML_SCHEMA_TYPE_NOTATION:
1143 return("notation declaration");
1144 default:
1145 return("Not a schema component");
1146 }
1147}
1148/**
1149 * xmlSchemaPResCompAttrErr:
1150 * @ctxt: the schema validation context
1151 * @error: the error code
1152 * @ownerDes: the designation of the owner
1153 * @ownerItem: the owner as a schema object
1154 * @ownerElem: the owner as an element node
1155 * @name: the name of the attribute holding the QName
1156 * @refName: the referenced local name
1157 * @refURI: the referenced namespace URI
1158 * @message: optional message
1159 *
1160 * Used to report QName attribute values that failed to resolve
1161 * to schema components.
1162 */
1163static void
1164xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1165 xmlParserErrors error,
1166 xmlChar **ownerDes,
1167 xmlSchemaTypePtr ownerItem,
1168 xmlNodePtr ownerElem,
1169 const char *name,
1170 const xmlChar *refName,
1171 const xmlChar *refURI,
1172 xmlSchemaTypeType refType,
1173 const char *refTypeStr)
1174{
1175 xmlChar *des = NULL, *strA = NULL;
1176
1177 if (ownerDes == NULL)
1178 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1179 else if (*ownerDes == NULL) {
1180 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1181 des = *ownerDes;
1182 } else
1183 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001184 if (refTypeStr == NULL)
1185 refTypeStr = xmlSchemaCompTypeToString(refType);
1186 xmlSchemaPErrExt(ctxt, ownerElem, error,
1187 NULL, NULL, NULL,
1188 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1189 "%s.\n", BAD_CAST des, BAD_CAST name,
1190 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1191 BAD_CAST refTypeStr, NULL);
1192 if (ownerDes == NULL)
1193 FREE_AND_NULL(des)
1194 FREE_AND_NULL(strA)
1195}
1196
William M. Brack2f2a6632004-08-20 23:09:47 +00001197/**
1198 * xmlSchemaPCustomAttrErr:
1199 * @ctxt: the schema parser context
1200 * @error: the error code
1201 * @ownerDes: the designation of the owner
1202 * @ownerItem: the owner as a schema object
1203 * @attr: the illegal attribute node
1204 *
1205 * Reports an illegal attribute during the parse.
1206 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001207static void
1208xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001209 xmlParserErrors error,
1210 xmlChar **ownerDes,
1211 xmlSchemaTypePtr ownerItem,
1212 xmlAttrPtr attr,
1213 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001214{
1215 xmlChar *des = NULL;
1216
1217 if (ownerDes == NULL)
1218 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1219 else if (*ownerDes == NULL) {
1220 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1221 des = *ownerDes;
1222 } else
1223 des = *ownerDes;
1224 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1225 "%s, attribute '%s': %s.\n",
1226 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1227 if (ownerDes == NULL)
1228 FREE_AND_NULL(des);
1229}
1230
1231/**
1232 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001233 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001234 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001235 * @ownerDes: the designation of the attribute's owner
1236 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001237 * @attr: the illegal attribute node
1238 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001239 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001240 */
1241static void
1242xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1243 xmlParserErrors error,
1244 xmlChar **ownerDes,
1245 xmlSchemaTypePtr ownerItem,
1246 xmlAttrPtr attr)
1247{
1248 xmlChar *des = NULL, *strA = NULL;
1249
1250 if (ownerDes == NULL)
1251 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1252 else if (*ownerDes == NULL) {
1253 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1254 des = *ownerDes;
1255 } else
1256 des = *ownerDes;
1257 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1258 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1259 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1260 if (ownerDes == NULL)
1261 FREE_AND_NULL(des);
1262 FREE_AND_NULL(strA);
1263}
1264
William M. Brack2f2a6632004-08-20 23:09:47 +00001265/**
1266 * xmlSchemaPAquireDes:
1267 * @des: the first designation
1268 * @itemDes: the second designation
1269 * @item: the schema item
1270 * @itemElem: the node of the schema item
1271 *
1272 * Creates a designation for an item.
1273 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001274static void
1275xmlSchemaPAquireDes(xmlChar **des,
1276 xmlChar **itemDes,
1277 xmlSchemaTypePtr item,
1278 xmlNodePtr itemElem)
1279{
1280 if (itemDes == NULL)
1281 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1282 else if (*itemDes == NULL) {
1283 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1284 *des = *itemDes;
1285 } else
1286 *des = *itemDes;
1287}
1288
William M. Brack2f2a6632004-08-20 23:09:47 +00001289/**
1290 * xmlSchemaPCustomErr:
1291 * @ctxt: the schema parser context
1292 * @error: the error code
1293 * @itemDes: the designation of the schema item
1294 * @item: the schema item
1295 * @itemElem: the node of the schema item
1296 * @message: the error message
1297 * @str1: an optional param for the error message
1298 * @str2: an optional param for the error message
1299 * @str3: an optional param for the error message
1300 *
1301 * Reports an error during parsing.
1302 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001303static void
1304xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1305 xmlParserErrors error,
1306 xmlChar **itemDes,
1307 xmlSchemaTypePtr item,
1308 xmlNodePtr itemElem,
1309 const char *message,
1310 const xmlChar *str1,
1311 const xmlChar *str2,
1312 const xmlChar *str3)
1313{
1314 xmlChar *des = NULL, *msg = NULL;
1315
1316 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1317 msg = xmlStrdup(BAD_CAST "%s: ");
1318 msg = xmlStrcat(msg, (const xmlChar *) message);
1319 msg = xmlStrcat(msg, BAD_CAST ".\n");
1320 if ((itemElem == NULL) && (item != NULL))
1321 itemElem = item->node;
1322 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1323 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1324 if (itemDes == NULL)
1325 FREE_AND_NULL(des);
1326 FREE_AND_NULL(msg);
1327}
1328
William M. Brack2f2a6632004-08-20 23:09:47 +00001329/**
1330 * xmlSchemaPCustomErr:
1331 * @ctxt: the schema parser context
1332 * @error: the error code
1333 * @itemDes: the designation of the schema item
1334 * @item: the schema item
1335 * @itemElem: the node of the schema item
1336 * @message: the error message
1337 * @str1: the optional param for the error message
1338 *
1339 * Reports an error during parsing.
1340 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001341static void
1342xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1343 xmlParserErrors error,
1344 xmlChar **itemDes,
1345 xmlSchemaTypePtr item,
1346 xmlNodePtr itemElem,
1347 const char *message,
1348 const xmlChar *str1)
1349{
1350 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1351 str1, NULL, NULL);
1352}
1353
William M. Brack2f2a6632004-08-20 23:09:47 +00001354/**
1355 * xmlSchemaPAttrUseErr:
1356 * @ctxt: the schema parser context
1357 * @error: the error code
1358 * @itemDes: the designation of the schema type
1359 * @item: the schema type
1360 * @itemElem: the node of the schema type
1361 * @attr: the invalid schema attribute
1362 * @message: the error message
1363 * @str1: the optional param for the error message
1364 *
1365 * Reports an attribute use error during parsing.
1366 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001367static void
1368xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1369 xmlParserErrors error,
1370 xmlChar **itemDes,
1371 xmlSchemaTypePtr item,
1372 xmlNodePtr itemElem,
1373 const xmlSchemaAttributePtr attr,
1374 const char *message,
1375 const xmlChar *str1)
1376{
1377 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1378
1379 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1380 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1381 xmlSchemaGetAttrName(attr));
1382 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1383 msg = xmlStrcat(msg, (const xmlChar *) message);
1384 msg = xmlStrcat(msg, BAD_CAST ".\n");
1385 if ((itemElem == NULL) && (item != NULL))
1386 itemElem = item->node;
1387 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1388 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1389 if (itemDes == NULL)
1390 FREE_AND_NULL(des);
1391 FREE_AND_NULL(strA);
1392 xmlFree(msg);
1393}
1394
William M. Brack2f2a6632004-08-20 23:09:47 +00001395/**
1396 * xmlSchemaPIllegalFacetAtomicErr:
1397 * @ctxt: the schema parser context
1398 * @error: the error code
1399 * @itemDes: the designation of the type
1400 * @item: the schema type
1401 * @baseItem: the base type of type
1402 * @facet: the illegal facet
1403 *
1404 * Reports an illegal facet for atomic simple types.
1405 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001406static void
1407xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1408 xmlParserErrors error,
1409 xmlChar **itemDes,
1410 xmlSchemaTypePtr item,
1411 xmlSchemaTypePtr baseItem,
1412 xmlSchemaFacetPtr facet)
1413{
1414 xmlChar *des = NULL, *strT = NULL;
1415
1416 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1417 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1418 "%s: The facet '%s' is not allowed on types derived from the "
1419 "type %s.\n",
1420 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1421 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1422 NULL, NULL);
1423 if (itemDes == NULL)
1424 FREE_AND_NULL(des);
1425 FREE_AND_NULL(strT);
1426}
1427
William M. Brack2f2a6632004-08-20 23:09:47 +00001428/**
1429 * xmlSchemaPIllegalFacetListUnionErr:
1430 * @ctxt: the schema parser context
1431 * @error: the error code
1432 * @itemDes: the designation of the schema item involved
1433 * @item: the schema item involved
1434 * @facet: the illegal facet
1435 *
1436 * Reports an illegal facet for <list> and <union>.
1437 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001438static void
1439xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1440 xmlParserErrors error,
1441 xmlChar **itemDes,
1442 xmlSchemaTypePtr item,
1443 xmlSchemaFacetPtr facet)
1444{
1445 xmlChar *des = NULL, *strT = NULL;
1446
1447 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1448 xmlSchemaPErr(ctxt, item->node, error,
1449 "%s: The facet '%s' is not allowed.\n",
1450 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1451 if (itemDes == NULL)
1452 FREE_AND_NULL(des);
1453 FREE_AND_NULL(strT);
1454}
1455
1456/**
1457 * xmlSchemaPMutualExclAttrErr:
1458 * @ctxt: the schema validation context
1459 * @error: the error code
1460 * @elemDes: the designation of the parent element node
1461 * @attr: the bad attribute node
1462 * @type: the corresponding type of the attribute node
1463 *
1464 * Reports an illegal attribute.
1465 */
1466static void
1467xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1468 xmlParserErrors error,
1469 xmlChar **ownerDes,
1470 xmlSchemaTypePtr ownerItem,
1471 xmlAttrPtr attr,
1472 const char *name1,
1473 const char *name2)
1474{
1475 xmlChar *des = NULL;
1476
1477 if (ownerDes == NULL)
1478 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1479 else if (*ownerDes == NULL) {
1480 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1481 des = *ownerDes;
1482 } else
1483 des = *ownerDes;
1484 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1485 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1486 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1487 if (ownerDes == NULL)
1488 FREE_AND_NULL(des)
1489}
1490
1491/**
1492 * xmlSchemaPSimpleTypeErr:
1493 * @ctxt: the schema validation context
1494 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001495 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001496 * @ownerDes: the designation of the owner
1497 * @ownerItem: the schema object if existent
1498 * @node: the validated node
1499 * @value: the validated value
1500 *
1501 * Reports a simple type validation error.
1502 * TODO: Should this report the value of an element as well?
1503 */
1504static void
1505xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1506 xmlParserErrors error,
1507 xmlChar **ownerDes,
1508 xmlSchemaTypePtr ownerItem,
1509 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001510 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001511 const char *typeDes,
1512 const xmlChar *value,
1513 const char *message,
1514 const xmlChar *str1,
1515 const xmlChar *str2)
1516{
William M. Brack2f2a6632004-08-20 23:09:47 +00001517 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001518
1519 if (ownerDes == NULL)
1520 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1521 else if (*ownerDes == NULL) {
1522 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1523 des = *ownerDes;
1524 } else
1525 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001526 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001527 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001528 if (message == NULL) {
1529 /*
1530 * Use default messages.
1531 */
1532 if (node->type == XML_ATTRIBUTE_NODE) {
1533 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1534 "%s, attribute '%s' [%s]: The value '%s' is not "
1535 "valid.\n",
1536 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1537 node->name), BAD_CAST typeDes, value, NULL);
1538 } else {
1539 xmlSchemaPErr(ctxt, node, error,
1540 "%s [%s]: The character content is not valid.\n",
1541 BAD_CAST des, BAD_CAST typeDes);
1542 }
1543 } else {
1544 xmlChar *msg;
1545
1546 msg = xmlStrdup(BAD_CAST "%s");
1547 if (node->type == XML_ATTRIBUTE_NODE)
1548 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1549 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1550 msg = xmlStrcat(msg, (const xmlChar *) message);
1551 msg = xmlStrcat(msg, BAD_CAST ".\n");
1552 if (node->type == XML_ATTRIBUTE_NODE) {
1553 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1554 (const char *) msg,
1555 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1556 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1557 } else {
1558 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1559 (const char *) msg,
1560 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1561 }
1562 xmlFree(msg);
1563 }
1564 /* Cleanup. */
1565 FREE_AND_NULL(strA)
1566 FREE_AND_NULL(strT)
1567 if (ownerDes == NULL)
1568 FREE_AND_NULL(des)
1569}
1570
William M. Brack2f2a6632004-08-20 23:09:47 +00001571/**
1572 * xmlSchemaPContentErr:
1573 * @ctxt: the schema parser context
1574 * @error: the error code
1575 * @onwerDes: the designation of the holder of the content
1576 * @ownerItem: the owner item of the holder of the content
1577 * @ownerElem: the node of the holder of the content
1578 * @child: the invalid child node
1579 * @message: the optional error message
1580 * @content: the optional string describing the correct content
1581 *
1582 * Reports an error concerning the content of a schema element.
1583 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001584static void
1585xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1586 xmlParserErrors error,
1587 xmlChar **ownerDes,
1588 xmlSchemaTypePtr ownerItem,
1589 xmlNodePtr ownerElem,
1590 xmlNodePtr child,
1591 const char *message,
1592 const char *content)
1593{
1594 xmlChar *des = NULL;
1595
1596 if (ownerDes == NULL)
1597 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1598 else if (*ownerDes == NULL) {
1599 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1600 des = *ownerDes;
1601 } else
1602 des = *ownerDes;
1603 if (message != NULL)
1604 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1605 "%s: %s.\n",
1606 BAD_CAST des, BAD_CAST message);
1607 else {
1608 if (content != NULL) {
1609 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1610 "%s: The content is not valid. Expected is %s.\n",
1611 BAD_CAST des, BAD_CAST content);
1612 } else {
1613 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1614 "%s: The content is not valid.\n",
1615 BAD_CAST des, NULL);
1616 }
1617 }
1618 if (ownerDes == NULL)
1619 FREE_AND_NULL(des)
1620}
1621
1622/**
1623 * xmlSchemaVIllegalAttrErr:
1624 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001625 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001626 * @attr: the illegal attribute node
1627 *
1628 * Reports an illegal attribute.
1629 */
1630static void
1631xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001632 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001633 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001634{
1635 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001636
1637 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1638 error,
1639 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001640 "%s: The attribute '%s' is not allowed.\n",
1641 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1642 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1643 FREE_AND_NULL(strE)
1644 FREE_AND_NULL(strA)
1645}
1646
William M. Brack2f2a6632004-08-20 23:09:47 +00001647/**
1648 * xmlSchemaVCustomErr:
1649 * @ctxt: the schema validation context
1650 * @error: the error code
1651 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001652 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001653 * @message: the error message
1654 * @str1: the optional param for the message
1655 *
1656 * Reports a validation error.
1657 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001658static void
1659xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1660 xmlParserErrors error,
1661 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001662 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001663 const char *message,
1664 const xmlChar *str1)
1665{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001666 xmlChar *msg = NULL, *str = NULL;
1667
1668 if (node == NULL) {
1669 xmlSchemaVErr(ctxt, NULL,
1670 XML_SCHEMAV_INTERNAL,
1671 "Internal error: xmlSchemaVCustomErr, no node "
1672 "given.\n", NULL, NULL);
1673 return;
1674 }
1675 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1676 if (node->type != XML_DOCUMENT_NODE) {
1677 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1678 if (type != NULL) {
1679 msg = xmlStrcat(msg, BAD_CAST " [");
1680 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1681 msg = xmlStrcat(msg, BAD_CAST "]");
1682 }
1683 msg = xmlStrcat(msg, BAD_CAST ": ");
1684 } else
1685 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001686 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001687 msg = xmlStrcat(msg, BAD_CAST ".\n");
1688 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1689 FREE_AND_NULL(msg)
1690 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001691}
1692
William M. Brack2f2a6632004-08-20 23:09:47 +00001693/**
1694 * xmlSchemaWildcardPCToString:
1695 * @pc: the type of processContents
1696 *
1697 * Returns a string representation of the type of
1698 * processContents.
1699 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001700static const char *
1701xmlSchemaWildcardPCToString(int pc)
1702{
1703 switch (pc) {
1704 case XML_SCHEMAS_ANY_SKIP:
1705 return ("skip");
1706 case XML_SCHEMAS_ANY_LAX:
1707 return ("lax");
1708 case XML_SCHEMAS_ANY_STRICT:
1709 return ("strict");
1710 default:
1711 return ("invalid process contents");
1712 }
1713}
1714
William M. Brack2f2a6632004-08-20 23:09:47 +00001715/**
1716 * xmlSchemaVWildcardErr:
1717 * @ctxt: the schema validation context
1718 * @error: the error code
1719 * @node: the validated node
1720 * @wild: the wildcard used
1721 * @message: the error message
1722 *
1723 * Reports an validation-by-wildcard error.
1724 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001725static void
1726xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaWildcardPtr wild,
1730 const char *message)
1731{
1732 xmlChar *des = NULL, *msg = NULL;
1733
1734 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1735 msg = xmlStrdup(BAD_CAST "%s, [");
1736 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
1737 msg = xmlStrcat(msg, BAD_CAST " WC]: ");
1738 msg = xmlStrcat(msg, (const xmlChar *) message);
1739 msg = xmlStrcat(msg, BAD_CAST ".\n");
1740 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1741 FREE_AND_NULL(des);
1742 FREE_AND_NULL(msg);
1743}
1744
1745/**
1746 * xmlSchemaVMissingAttrErr:
1747 * @ctxt: the schema validation context
1748 * @node: the parent element node of the missing attribute node
1749 * @type: the corresponding type of the attribute node
1750 *
1751 * Reports an illegal attribute.
1752 */
1753static void
1754xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1755 xmlNodePtr elem,
1756 xmlSchemaAttributePtr type)
1757{
1758 const xmlChar *name, *uri;
1759 xmlChar *strE = NULL, *strA = NULL;
1760
1761 if (type->ref != NULL) {
1762 name = type->ref;
1763 uri = type->refNs;
1764 } else {
1765 name = type->name;
1766 uri = type->targetNamespace;
1767 }
1768 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001769 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1770 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001771 "%s: The attribute %s is required but missing.\n",
1772 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1773 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1774 FREE_AND_NULL(strE)
1775 FREE_AND_NULL(strA)
1776}
1777
Daniel Veillard4255d502002-04-16 15:50:10 +00001778/************************************************************************
1779 * *
1780 * Allocation functions *
1781 * *
1782 ************************************************************************/
1783
1784/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001785 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001786 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001787 *
1788 * Allocate a new Schema structure.
1789 *
1790 * Returns the newly allocated structure or NULL in case or error
1791 */
1792static xmlSchemaPtr
1793xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1794{
1795 xmlSchemaPtr ret;
1796
1797 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1798 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001799 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001800 return (NULL);
1801 }
1802 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001803 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001804 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001805
1806 return (ret);
1807}
1808
1809/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001810 * xmlSchemaNewSchema:
1811 * @ctxt: a schema validation context
1812 *
1813 * Allocate a new Schema structure.
1814 *
1815 * Returns the newly allocated structure or NULL in case or error
1816 */
1817static xmlSchemaAssemblePtr
1818xmlSchemaNewAssemble(void)
1819{
1820 xmlSchemaAssemblePtr ret;
1821
1822 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1823 if (ret == NULL) {
1824 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1825 return (NULL);
1826 }
1827 memset(ret, 0, sizeof(xmlSchemaAssemble));
1828 ret->items = NULL;
1829 return (ret);
1830}
1831
1832/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001833 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001834 *
1835 * Allocate a new Facet structure.
1836 *
1837 * Returns the newly allocated structure or NULL in case or error
1838 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001839xmlSchemaFacetPtr
1840xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001841{
1842 xmlSchemaFacetPtr ret;
1843
1844 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1845 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001846 return (NULL);
1847 }
1848 memset(ret, 0, sizeof(xmlSchemaFacet));
1849
1850 return (ret);
1851}
1852
1853/**
1854 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001855 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001856 * @node: a node
1857 *
1858 * Allocate a new annotation structure.
1859 *
1860 * Returns the newly allocated structure or NULL in case or error
1861 */
1862static xmlSchemaAnnotPtr
1863xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1864{
1865 xmlSchemaAnnotPtr ret;
1866
1867 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1868 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001869 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001870 return (NULL);
1871 }
1872 memset(ret, 0, sizeof(xmlSchemaAnnot));
1873 ret->content = node;
1874 return (ret);
1875}
1876
1877/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001878 * xmlSchemaFreeAnnot:
1879 * @annot: a schema type structure
1880 *
1881 * Deallocate a annotation structure
1882 */
1883static void
1884xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1885{
1886 if (annot == NULL)
1887 return;
1888 xmlFree(annot);
1889}
1890
1891/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001892 * xmlSchemaFreeImport:
1893 * @import: a schema import structure
1894 *
1895 * Deallocate an import structure
1896 */
1897static void
1898xmlSchemaFreeImport(xmlSchemaImportPtr import)
1899{
1900 if (import == NULL)
1901 return;
1902
1903 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001904 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001905 xmlFree(import);
1906}
1907
1908/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001909 * xmlSchemaFreeInclude:
1910 * @include: a schema include structure
1911 *
1912 * Deallocate an include structure
1913 */
1914static void
1915xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1916{
1917 if (include == NULL)
1918 return;
1919
1920 xmlFreeDoc(include->doc);
1921 xmlFree(include);
1922}
1923
1924/**
1925 * xmlSchemaFreeIncludeList:
1926 * @includes: a schema include list
1927 *
1928 * Deallocate an include structure
1929 */
1930static void
1931xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1932{
1933 xmlSchemaIncludePtr next;
1934
1935 while (includes != NULL) {
1936 next = includes->next;
1937 xmlSchemaFreeInclude(includes);
1938 includes = next;
1939 }
1940}
1941
1942/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001943 * xmlSchemaFreeNotation:
1944 * @schema: a schema notation structure
1945 *
1946 * Deallocate a Schema Notation structure.
1947 */
1948static void
1949xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1950{
1951 if (nota == NULL)
1952 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001953 xmlFree(nota);
1954}
1955
1956/**
1957 * xmlSchemaFreeAttribute:
1958 * @schema: a schema attribute structure
1959 *
1960 * Deallocate a Schema Attribute structure.
1961 */
1962static void
1963xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
1964{
1965 if (attr == NULL)
1966 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001967 if (attr->annot != NULL)
1968 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001969 if (attr->defVal != NULL)
1970 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00001971 xmlFree(attr);
1972}
1973
1974/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001975 * xmlSchemaFreeWildcardNsSet:
1976 * set: a schema wildcard namespace
1977 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001978 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00001979 */
1980static void
1981xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
1982{
1983 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001984
Daniel Veillard3646d642004-06-02 19:19:14 +00001985 while (set != NULL) {
1986 next = set->next;
1987 xmlFree(set);
1988 set = next;
1989 }
1990}
1991
1992/**
1993 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001994 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00001995 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001996 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00001997 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00001998void
Daniel Veillard3646d642004-06-02 19:19:14 +00001999xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2000{
2001 if (wildcard == NULL)
2002 return;
2003 if (wildcard->annot != NULL)
2004 xmlSchemaFreeAnnot(wildcard->annot);
2005 if (wildcard->nsSet != NULL)
2006 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2007 if (wildcard->negNsSet != NULL)
2008 xmlFree(wildcard->negNsSet);
2009 xmlFree(wildcard);
2010}
2011
2012/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002013 * xmlSchemaFreeAttributeGroup:
2014 * @schema: a schema attribute group structure
2015 *
2016 * Deallocate a Schema Attribute Group structure.
2017 */
2018static void
2019xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2020{
2021 if (attr == NULL)
2022 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002023 if (attr->annot != NULL)
2024 xmlSchemaFreeAnnot(attr->annot);
2025 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2026 (attr->attributeWildcard != NULL))
2027 xmlSchemaFreeWildcard(attr->attributeWildcard);
2028
Daniel Veillard4255d502002-04-16 15:50:10 +00002029 xmlFree(attr);
2030}
2031
2032/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002033 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002034 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002035 *
2036 * Deallocate a list of schema attribute uses.
2037 */
2038static void
2039xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2040{
2041 xmlSchemaAttributeLinkPtr next;
2042
2043 while (attrUse != NULL) {
2044 next = attrUse->next;
2045 xmlFree(attrUse);
2046 attrUse = next;
2047 }
2048}
2049
2050/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002051 * xmlSchemaFreeTypeLinkList:
2052 * @alink: a type link
2053 *
2054 * Deallocate a list of types.
2055 */
2056static void
2057xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2058{
2059 xmlSchemaTypeLinkPtr next;
2060
2061 while (link != NULL) {
2062 next = link->next;
2063 xmlFree(link);
2064 link = next;
2065 }
2066}
2067
2068/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002069 * xmlSchemaFreeElement:
2070 * @schema: a schema element structure
2071 *
2072 * Deallocate a Schema Element structure.
2073 */
2074static void
2075xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2076{
2077 if (elem == NULL)
2078 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002079 if (elem->annot != NULL)
2080 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002081 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002082 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002083 if (elem->defVal != NULL)
2084 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002085 xmlFree(elem);
2086}
2087
2088/**
2089 * xmlSchemaFreeFacet:
2090 * @facet: a schema facet structure
2091 *
2092 * Deallocate a Schema Facet structure.
2093 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002094void
Daniel Veillard4255d502002-04-16 15:50:10 +00002095xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2096{
2097 if (facet == NULL)
2098 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002099 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002100 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002101 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002102 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002103 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002104 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002105 xmlFree(facet);
2106}
2107
2108/**
2109 * xmlSchemaFreeType:
2110 * @type: a schema type structure
2111 *
2112 * Deallocate a Schema Type structure.
2113 */
2114void
2115xmlSchemaFreeType(xmlSchemaTypePtr type)
2116{
2117 if (type == NULL)
2118 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002119 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002120 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002121 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002122 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002123
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002124 facet = type->facets;
2125 while (facet != NULL) {
2126 next = facet->next;
2127 xmlSchemaFreeFacet(facet);
2128 facet = next;
2129 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002130 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002131 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2132 if (type->attributeUses != NULL)
2133 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002134 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002135 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002136 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2137 /*
2138 * NOTE: The only case where an attribute wildcard
2139 * is not owned, is if a complex type inherits it
2140 * from a base type.
2141 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002142 xmlSchemaFreeWildcard(type->attributeWildcard);
2143 }
2144 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002145 if (type->memberTypes != NULL)
2146 xmlSchemaFreeTypeLinkList(type->memberTypes);
2147 if (type->facetSet != NULL) {
2148 xmlSchemaFacetLinkPtr next, link;
2149
2150 link = type->facetSet;
2151 do {
2152 next = link->next;
2153 xmlFree(link);
2154 link = next;
2155 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002156 }
2157 if (type->contModel != NULL)
2158 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002159 xmlFree(type);
2160}
2161
2162/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002163 * xmlSchemaFreeTypeList:
2164 * @type: a schema type structure
2165 *
2166 * Deallocate a Schema Type structure.
2167 */
2168static void
2169xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2170{
2171 xmlSchemaTypePtr next;
2172
2173 while (type != NULL) {
2174 next = type->redef;
2175 xmlSchemaFreeType(type);
2176 type = next;
2177 }
2178}
2179
2180/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002181 * xmlSchemaFree:
2182 * @schema: a schema structure
2183 *
2184 * Deallocate a Schema structure.
2185 */
2186void
2187xmlSchemaFree(xmlSchemaPtr schema)
2188{
2189 if (schema == NULL)
2190 return;
2191
Daniel Veillard4255d502002-04-16 15:50:10 +00002192 if (schema->notaDecl != NULL)
2193 xmlHashFree(schema->notaDecl,
2194 (xmlHashDeallocator) xmlSchemaFreeNotation);
2195 if (schema->attrDecl != NULL)
2196 xmlHashFree(schema->attrDecl,
2197 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2198 if (schema->attrgrpDecl != NULL)
2199 xmlHashFree(schema->attrgrpDecl,
2200 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2201 if (schema->elemDecl != NULL)
2202 xmlHashFree(schema->elemDecl,
2203 (xmlHashDeallocator) xmlSchemaFreeElement);
2204 if (schema->typeDecl != NULL)
2205 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002206 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002207 if (schema->groupDecl != NULL)
2208 xmlHashFree(schema->groupDecl,
2209 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002210 if (schema->schemasImports != NULL)
2211 xmlHashFree(schema->schemasImports,
2212 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002213 if (schema->includes != NULL) {
2214 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2215 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002216 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002217 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002218 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002219 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002220 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002221 xmlFree(schema);
2222}
2223
2224/************************************************************************
2225 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002226 * Debug functions *
2227 * *
2228 ************************************************************************/
2229
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002230#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231
Daniel Veillard4255d502002-04-16 15:50:10 +00002232/**
2233 * xmlSchemaElementDump:
2234 * @elem: an element
2235 * @output: the file output
2236 *
2237 * Dump the element
2238 */
2239static void
2240xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002241 const xmlChar * name ATTRIBUTE_UNUSED,
2242 const xmlChar * context ATTRIBUTE_UNUSED,
2243 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002244{
2245 if (elem == NULL)
2246 return;
2247
2248 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002249 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2250 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 fprintf(output, ": %s ", elem->name);
2252 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 fprintf(output, "namespace '%s' ", namespace);
2254
Daniel Veillard4255d502002-04-16 15:50:10 +00002255 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002256 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002257 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002258 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002259 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002260 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002261 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002262 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002263 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002264 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002265 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002266 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002267 fprintf(output, "\n");
2268 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002269 fprintf(output, " ");
2270 if (elem->minOccurs != 1)
2271 fprintf(output, "min: %d ", elem->minOccurs);
2272 if (elem->maxOccurs >= UNBOUNDED)
2273 fprintf(output, "max: unbounded\n");
2274 else if (elem->maxOccurs != 1)
2275 fprintf(output, "max: %d\n", elem->maxOccurs);
2276 else
2277 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002278 }
2279 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002280 fprintf(output, " type: %s", elem->namedType);
2281 if (elem->namedTypeNs != NULL)
2282 fprintf(output, " ns %s\n", elem->namedTypeNs);
2283 else
2284 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002285 }
2286 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002287 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2288 if (elem->substGroupNs != NULL)
2289 fprintf(output, " ns %s\n", elem->substGroupNs);
2290 else
2291 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002292 }
2293 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002294 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002295}
2296
2297/**
2298 * xmlSchemaAnnotDump:
2299 * @output: the file output
2300 * @annot: a annotation
2301 *
2302 * Dump the annotation
2303 */
2304static void
2305xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2306{
2307 xmlChar *content;
2308
2309 if (annot == NULL)
2310 return;
2311
2312 content = xmlNodeGetContent(annot->content);
2313 if (content != NULL) {
2314 fprintf(output, " Annot: %s\n", content);
2315 xmlFree(content);
2316 } else
2317 fprintf(output, " Annot: empty\n");
2318}
2319
2320/**
2321 * xmlSchemaTypeDump:
2322 * @output: the file output
2323 * @type: a type structure
2324 *
2325 * Dump a SchemaType structure
2326 */
2327static void
2328xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2329{
2330 if (type == NULL) {
2331 fprintf(output, "Type: NULL\n");
2332 return;
2333 }
2334 fprintf(output, "Type: ");
2335 if (type->name != NULL)
2336 fprintf(output, "%s, ", type->name);
2337 else
2338 fprintf(output, "no name");
2339 switch (type->type) {
2340 case XML_SCHEMA_TYPE_BASIC:
2341 fprintf(output, "basic ");
2342 break;
2343 case XML_SCHEMA_TYPE_SIMPLE:
2344 fprintf(output, "simple ");
2345 break;
2346 case XML_SCHEMA_TYPE_COMPLEX:
2347 fprintf(output, "complex ");
2348 break;
2349 case XML_SCHEMA_TYPE_SEQUENCE:
2350 fprintf(output, "sequence ");
2351 break;
2352 case XML_SCHEMA_TYPE_CHOICE:
2353 fprintf(output, "choice ");
2354 break;
2355 case XML_SCHEMA_TYPE_ALL:
2356 fprintf(output, "all ");
2357 break;
2358 case XML_SCHEMA_TYPE_UR:
2359 fprintf(output, "ur ");
2360 break;
2361 case XML_SCHEMA_TYPE_RESTRICTION:
2362 fprintf(output, "restriction ");
2363 break;
2364 case XML_SCHEMA_TYPE_EXTENSION:
2365 fprintf(output, "extension ");
2366 break;
2367 default:
2368 fprintf(output, "unknowntype%d ", type->type);
2369 break;
2370 }
2371 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002372 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002373 }
2374 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002375 case XML_SCHEMA_CONTENT_UNKNOWN:
2376 fprintf(output, "unknown ");
2377 break;
2378 case XML_SCHEMA_CONTENT_EMPTY:
2379 fprintf(output, "empty ");
2380 break;
2381 case XML_SCHEMA_CONTENT_ELEMENTS:
2382 fprintf(output, "element ");
2383 break;
2384 case XML_SCHEMA_CONTENT_MIXED:
2385 fprintf(output, "mixed ");
2386 break;
2387 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002388 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002389 break;
2390 case XML_SCHEMA_CONTENT_BASIC:
2391 fprintf(output, "basic ");
2392 break;
2393 case XML_SCHEMA_CONTENT_SIMPLE:
2394 fprintf(output, "simple ");
2395 break;
2396 case XML_SCHEMA_CONTENT_ANY:
2397 fprintf(output, "any ");
2398 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002399 }
2400 fprintf(output, "\n");
2401 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002402 fprintf(output, " ");
2403 if (type->minOccurs != 1)
2404 fprintf(output, "min: %d ", type->minOccurs);
2405 if (type->maxOccurs >= UNBOUNDED)
2406 fprintf(output, "max: unbounded\n");
2407 else if (type->maxOccurs != 1)
2408 fprintf(output, "max: %d\n", type->maxOccurs);
2409 else
2410 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002411 }
2412 if (type->annot != NULL)
2413 xmlSchemaAnnotDump(output, type->annot);
2414 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002416
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002417 fprintf(output, " subtypes: ");
2418 while (sub != NULL) {
2419 fprintf(output, "%s ", sub->name);
2420 sub = sub->next;
2421 }
2422 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002423 }
2424
2425}
2426
2427/**
2428 * xmlSchemaDump:
2429 * @output: the file output
2430 * @schema: a schema structure
2431 *
2432 * Dump a Schema structure.
2433 */
2434void
2435xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2436{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002437 if (output == NULL)
2438 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002439 if (schema == NULL) {
2440 fprintf(output, "Schemas: NULL\n");
2441 return;
2442 }
2443 fprintf(output, "Schemas: ");
2444 if (schema->name != NULL)
2445 fprintf(output, "%s, ", schema->name);
2446 else
2447 fprintf(output, "no name, ");
2448 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002449 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002450 else
2451 fprintf(output, "no target namespace");
2452 fprintf(output, "\n");
2453 if (schema->annot != NULL)
2454 xmlSchemaAnnotDump(output, schema->annot);
2455
2456 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2457 output);
2458 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002459 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002460}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002461#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002462
2463/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002464 * *
2465 * Utilities *
2466 * *
2467 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002468
Daniel Veillardc0826a72004-08-10 14:17:33 +00002469/**
2470 * xmlSchemaGetPropNode:
2471 * @node: the element node
2472 * @name: the name of the attribute
2473 *
2474 * Seeks an attribute with a name of @name in
2475 * no namespace.
2476 *
2477 * Returns the attribute or NULL if not present.
2478 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002479static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002480xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002481{
2482 xmlAttrPtr prop;
2483
Daniel Veillardc0826a72004-08-10 14:17:33 +00002484 if ((node == NULL) || (name == NULL))
2485 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002486 prop = node->properties;
2487 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002488 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2489 return(prop);
2490 prop = prop->next;
2491 }
2492 return (NULL);
2493}
2494
2495/**
2496 * xmlSchemaGetPropNodeNs:
2497 * @node: the element node
2498 * @uri: the uri
2499 * @name: the name of the attribute
2500 *
2501 * Seeks an attribute with a local name of @name and
2502 * a namespace URI of @uri.
2503 *
2504 * Returns the attribute or NULL if not present.
2505 */
2506static xmlAttrPtr
2507xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2508{
2509 xmlAttrPtr prop;
2510
2511 if ((node == NULL) || (name == NULL))
2512 return(NULL);
2513 prop = node->properties;
2514 while (prop != NULL) {
2515 if ((prop->ns != NULL) &&
2516 xmlStrEqual(prop->name, BAD_CAST name) &&
2517 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002518 return(prop);
2519 prop = prop->next;
2520 }
2521 return (NULL);
2522}
2523
2524static const xmlChar *
2525xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2526{
2527 xmlChar *val;
2528 const xmlChar *ret;
2529
2530 val = xmlNodeGetContent(node);
2531 if (val == NULL)
2532 return(NULL);
2533 ret = xmlDictLookup(ctxt->dict, val, -1);
2534 xmlFree(val);
2535 return(ret);
2536}
2537
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002538/**
2539 * xmlSchemaGetProp:
2540 * @ctxt: the parser context
2541 * @node: the node
2542 * @name: the property name
2543 *
2544 * Read a attribute value and internalize the string
2545 *
2546 * Returns the string or NULL if not present.
2547 */
2548static const xmlChar *
2549xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2550 const char *name)
2551{
2552 xmlChar *val;
2553 const xmlChar *ret;
2554
2555 val = xmlGetProp(node, BAD_CAST name);
2556 if (val == NULL)
2557 return(NULL);
2558 ret = xmlDictLookup(ctxt->dict, val, -1);
2559 xmlFree(val);
2560 return(ret);
2561}
2562
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002563/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002564 * *
2565 * Parsing functions *
2566 * *
2567 ************************************************************************/
2568
2569/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002570 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002571 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002572 * @name: the element name
2573 * @ns: the element namespace
2574 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002575 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002576 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002577 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002578 */
2579static xmlSchemaElementPtr
2580xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002581 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002582{
2583 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002584
2585 if ((name == NULL) || (schema == NULL))
2586 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002587
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002588 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002589 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002590 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002591 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002592 } else
2593 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002594 /*
2595 * This one was removed, since top level element declarations have
2596 * the target namespace specified in targetNamespace of the <schema>
2597 * information element, even if elementFormDefault is "unqualified".
2598 */
2599
2600 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002601 if (xmlStrEqual(namespace, schema->targetNamespace))
2602 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2603 else
2604 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002605 if ((ret != NULL) &&
2606 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002607 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002608 }
William M. Bracke7091952004-05-11 15:09:58 +00002609 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002610
William M. Brack2f2a6632004-08-20 23:09:47 +00002611 /*
2612 * Removed since imported components will be hold by the main schema only.
2613 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002614 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002615 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002616 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002617 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002618 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002619 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002620 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2621 return (ret);
2622 } else
2623 ret = NULL;
2624 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002625 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002626#ifdef DEBUG
2627 if (ret == NULL) {
2628 if (namespace == NULL)
2629 fprintf(stderr, "Unable to lookup type %s", name);
2630 else
2631 fprintf(stderr, "Unable to lookup type %s:%s", name,
2632 namespace);
2633 }
2634#endif
2635 return (ret);
2636}
2637
2638/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002639 * xmlSchemaGetType:
2640 * @schema: the schemas context
2641 * @name: the type name
2642 * @ns: the type namespace
2643 *
2644 * Lookup a type in the schemas or the predefined types
2645 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002646 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002647 */
2648static xmlSchemaTypePtr
2649xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002650 const xmlChar * namespace)
2651{
Daniel Veillard4255d502002-04-16 15:50:10 +00002652 xmlSchemaTypePtr ret;
2653
2654 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002656 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002657 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002658 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002659 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002660 }
2661 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002662 if (ret != NULL)
2663 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002664 /*
2665 * Removed, since the imported components will be grafted on the
2666 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002667 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002668 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002669 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002670 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002671 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002672 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002673 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2674 return (ret);
2675 } else
2676 ret = NULL;
2677 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002678 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002679#ifdef DEBUG
2680 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002681 if (namespace == NULL)
2682 fprintf(stderr, "Unable to lookup type %s", name);
2683 else
2684 fprintf(stderr, "Unable to lookup type %s:%s", name,
2685 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002686 }
2687#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002688 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002689}
2690
Daniel Veillard3646d642004-06-02 19:19:14 +00002691/**
2692 * xmlSchemaGetAttribute:
2693 * @schema: the context of the schema
2694 * @name: the name of the attribute
2695 * @ns: the target namespace of the attribute
2696 *
2697 * Lookup a an attribute in the schema or imported schemas
2698 *
2699 * Returns the attribute declaration or NULL if not found.
2700 */
2701static xmlSchemaAttributePtr
2702xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2703 const xmlChar * namespace)
2704{
2705 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002706
2707 if ((name == NULL) || (schema == NULL))
2708 return (NULL);
2709
2710
2711 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2712 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2713 return (ret);
2714 else
2715 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002716 /*
2717 * Removed, since imported components will be hold by the main schema only.
2718 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002719 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002720 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002721 else
2722 import = xmlHashLookup(schema->schemasImports, namespace);
2723 if (import != NULL) {
2724 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2725 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2726 return (ret);
2727 } else
2728 ret = NULL;
2729 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002730 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002731#ifdef DEBUG
2732 if (ret == NULL) {
2733 if (namespace == NULL)
2734 fprintf(stderr, "Unable to lookup attribute %s", name);
2735 else
2736 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2737 namespace);
2738 }
2739#endif
2740 return (ret);
2741}
2742
2743/**
2744 * xmlSchemaGetAttributeGroup:
2745 * @schema: the context of the schema
2746 * @name: the name of the attribute group
2747 * @ns: the target namespace of the attribute group
2748 *
2749 * Lookup a an attribute group in the schema or imported schemas
2750 *
2751 * Returns the attribute group definition or NULL if not found.
2752 */
2753static xmlSchemaAttributeGroupPtr
2754xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2755 const xmlChar * namespace)
2756{
2757 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002758
2759 if ((name == NULL) || (schema == NULL))
2760 return (NULL);
2761
2762
2763 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2764 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2765 return (ret);
2766 else
2767 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002768 /*
2769 * Removed since imported components will be hold by the main schema only.
2770 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002771 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002772 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002773 else
2774 import = xmlHashLookup(schema->schemasImports, namespace);
2775 if (import != NULL) {
2776 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2777 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2778 return (ret);
2779 else
2780 ret = NULL;
2781 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002782 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002783#ifdef DEBUG
2784 if (ret == NULL) {
2785 if (namespace == NULL)
2786 fprintf(stderr, "Unable to lookup attribute group %s", name);
2787 else
2788 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2789 namespace);
2790 }
2791#endif
2792 return (ret);
2793}
2794
2795/**
2796 * xmlSchemaGetGroup:
2797 * @schema: the context of the schema
2798 * @name: the name of the group
2799 * @ns: the target namespace of the group
2800 *
2801 * Lookup a group in the schema or imported schemas
2802 *
2803 * Returns the group definition or NULL if not found.
2804 */
2805static xmlSchemaTypePtr
2806xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2807 const xmlChar * namespace)
2808{
2809 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002810
2811 if ((name == NULL) || (schema == NULL))
2812 return (NULL);
2813
2814
2815 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2816 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2817 return (ret);
2818 else
2819 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002820 /*
2821 * Removed since imported components will be hold by the main schema only.
2822 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002823 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002824 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002825 else
2826 import = xmlHashLookup(schema->schemasImports, namespace);
2827 if (import != NULL) {
2828 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2829 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2830 return (ret);
2831 else
2832 ret = NULL;
2833 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002834 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002835#ifdef DEBUG
2836 if (ret == NULL) {
2837 if (namespace == NULL)
2838 fprintf(stderr, "Unable to lookup group %s", name);
2839 else
2840 fprintf(stderr, "Unable to lookup group %s:%s", name,
2841 namespace);
2842 }
2843#endif
2844 return (ret);
2845}
2846
Daniel Veillard4255d502002-04-16 15:50:10 +00002847/************************************************************************
2848 * *
2849 * Parsing functions *
2850 * *
2851 ************************************************************************/
2852
2853#define IS_BLANK_NODE(n) \
2854 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2855
2856/**
2857 * xmlSchemaIsBlank:
2858 * @str: a string
2859 *
2860 * Check if a string is ignorable
2861 *
2862 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2863 */
2864static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002865xmlSchemaIsBlank(xmlChar * str)
2866{
Daniel Veillard4255d502002-04-16 15:50:10 +00002867 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002868 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002869 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002870 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002871 return (0);
2872 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002873 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002874 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002875}
2876
2877/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002878 * xmlSchemaAddAssembledItem:
2879 * @ctxt: a schema parser context
2880 * @schema: the schema being built
2881 * @item: the item
2882 *
2883 * Add a item to the schema's list of current items.
2884 * This is used if the schema was already constructed and
2885 * new schemata need to be added to it.
2886 * *WARNING* this interface is highly subject to change.
2887 *
2888 * Returns 0 if suceeds and -1 if an internal error occurs.
2889 */
2890static int
2891xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
2892 xmlSchemaTypePtr item)
2893{
2894 static int growSize = 100;
2895 xmlSchemaAssemblePtr ass;
2896
2897 ass = ctxt->assemble;
2898 if (ass->sizeItems < 0) {
2899 /* If disabled. */
2900 return (0);
2901 }
2902 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002903 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002904 if (ass->items == NULL) {
2905 xmlSchemaPErrMemory(ctxt,
2906 "allocating new item buffer", NULL);
2907 return (-1);
2908 }
2909 ass->sizeItems = growSize;
2910 } else if (ass->sizeItems <= ass->nbItems) {
2911 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002912 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002913 ass->sizeItems * sizeof(xmlSchemaTypePtr));
2914 if (ass->items == NULL) {
2915 xmlSchemaPErrMemory(ctxt,
2916 "growing item buffer", NULL);
2917 ass->sizeItems = 0;
2918 return (-1);
2919 }
2920 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002921 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002922 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
2923 return (0);
2924}
2925
2926/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002927 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002928 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 * @schema: the schema being built
2930 * @name: the item name
2931 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002932 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002933 * *WARNING* this interface is highly subject to change
2934 *
2935 * Returns the new struture or NULL in case of error
2936 */
2937static xmlSchemaNotationPtr
2938xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002939 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002940{
2941 xmlSchemaNotationPtr ret = NULL;
2942 int val;
2943
2944 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2945 return (NULL);
2946
2947 if (schema->notaDecl == NULL)
2948 schema->notaDecl = xmlHashCreate(10);
2949 if (schema->notaDecl == NULL)
2950 return (NULL);
2951
2952 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2953 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002954 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002955 return (NULL);
2956 }
2957 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002958 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002959 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2960 ret);
2961 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002962 /*
2963 * TODO: This should never happen, since a unique name will be computed.
2964 * If it fails, then an other internal error must have occured.
2965 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002966 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2967 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002968 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002969 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002970 xmlFree(ret);
2971 return (NULL);
2972 }
2973 return (ret);
2974}
2975
2976
2977/**
2978 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002979 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002980 * @schema: the schema being built
2981 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002982 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002983 *
2984 * Add an XML schema Attrribute declaration
2985 * *WARNING* this interface is highly subject to change
2986 *
2987 * Returns the new struture or NULL in case of error
2988 */
2989static xmlSchemaAttributePtr
2990xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002991 const xmlChar * name, const xmlChar * namespace,
2992 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002993{
2994 xmlSchemaAttributePtr ret = NULL;
2995 int val;
2996
2997 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2998 return (NULL);
2999
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003000#ifdef DEBUG
3001 fprintf(stderr, "Adding attribute %s\n", name);
3002 if (namespace != NULL)
3003 fprintf(stderr, " target namespace %s\n", namespace);
3004#endif
3005
Daniel Veillard4255d502002-04-16 15:50:10 +00003006 if (schema->attrDecl == NULL)
3007 schema->attrDecl = xmlHashCreate(10);
3008 if (schema->attrDecl == NULL)
3009 return (NULL);
3010
3011 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3012 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003013 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003014 return (NULL);
3015 }
3016 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003017 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3018 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003020 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003021 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003022 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003023 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003024 NULL, NULL, node,
3025 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003026 xmlFree(ret);
3027 return (NULL);
3028 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003029 if (ctxt->assemble != NULL)
3030 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003031 return (ret);
3032}
3033
3034/**
3035 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003036 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003037 * @schema: the schema being built
3038 * @name: the item name
3039 *
3040 * Add an XML schema Attrribute Group declaration
3041 *
3042 * Returns the new struture or NULL in case of error
3043 */
3044static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003045xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003046 xmlSchemaPtr schema, const xmlChar * name,
3047 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003048{
3049 xmlSchemaAttributeGroupPtr ret = NULL;
3050 int val;
3051
3052 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3053 return (NULL);
3054
3055 if (schema->attrgrpDecl == NULL)
3056 schema->attrgrpDecl = xmlHashCreate(10);
3057 if (schema->attrgrpDecl == NULL)
3058 return (NULL);
3059
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003060 ret =
3061 (xmlSchemaAttributeGroupPtr)
3062 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003063 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003064 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003065 return (NULL);
3066 }
3067 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003068 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003069 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003070 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003071 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003072 xmlSchemaPCustomErr(ctxt,
3073 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3074 NULL, NULL, node,
3075 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003076 xmlFree(ret);
3077 return (NULL);
3078 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003079 if (ctxt->assemble != NULL)
3080 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003081 return (ret);
3082}
3083
3084/**
3085 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003086 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003087 * @schema: the schema being built
3088 * @name: the type name
3089 * @namespace: the type namespace
3090 *
3091 * Add an XML schema Element declaration
3092 * *WARNING* this interface is highly subject to change
3093 *
3094 * Returns the new struture or NULL in case of error
3095 */
3096static xmlSchemaElementPtr
3097xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003098 const xmlChar * name, const xmlChar * namespace,
3099 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003100{
3101 xmlSchemaElementPtr ret = NULL;
3102 int val;
3103
3104 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3105 return (NULL);
3106
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003107#ifdef DEBUG
3108 fprintf(stderr, "Adding element %s\n", name);
3109 if (namespace != NULL)
3110 fprintf(stderr, " target namespace %s\n", namespace);
3111#endif
3112
Daniel Veillard4255d502002-04-16 15:50:10 +00003113 if (schema->elemDecl == NULL)
3114 schema->elemDecl = xmlHashCreate(10);
3115 if (schema->elemDecl == NULL)
3116 return (NULL);
3117
3118 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3119 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003120 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003121 return (NULL);
3122 }
3123 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003124 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3125 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003126 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003127 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003128 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003129 if (topLevel) {
3130 xmlSchemaPCustomErr(ctxt,
3131 XML_SCHEMAP_REDEFINED_ELEMENT,
3132 NULL, NULL, node,
3133 "A global element declaration with the name '%s' does "
3134 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003135 xmlFree(ret);
3136 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003137 } else {
3138 char buf[30];
3139
3140 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3141 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3142 namespace, ret);
3143 if (val != 0) {
3144 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003145 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003146 NULL, NULL, node,
3147 "Internal error: xmlSchemaAddElement, "
3148 "a dublicate element declaration with the name '%s' "
3149 "could not be added to the hash.", name);
3150 xmlFree(ret);
3151 return (NULL);
3152 }
3153 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003154
Daniel Veillard4255d502002-04-16 15:50:10 +00003155 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003156 if (ctxt->assemble != NULL)
3157 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 return (ret);
3159}
3160
3161/**
3162 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003163 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003164 * @schema: the schema being built
3165 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003166 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003167 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003168 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003169 * *WARNING* this interface is highly subject to change
3170 *
3171 * Returns the new struture or NULL in case of error
3172 */
3173static xmlSchemaTypePtr
3174xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003175 const xmlChar * name, const xmlChar * namespace,
3176 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003177{
3178 xmlSchemaTypePtr ret = NULL;
3179 int val;
3180
3181 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3182 return (NULL);
3183
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003184#ifdef DEBUG
3185 fprintf(stderr, "Adding type %s\n", name);
3186 if (namespace != NULL)
3187 fprintf(stderr, " target namespace %s\n", namespace);
3188#endif
3189
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 if (schema->typeDecl == NULL)
3191 schema->typeDecl = xmlHashCreate(10);
3192 if (schema->typeDecl == NULL)
3193 return (NULL);
3194
3195 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3196 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003197 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003198 return (NULL);
3199 }
3200 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003201 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003202 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003203 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003204 if (val != 0) {
3205 if (ctxt->includes == 0) {
3206 xmlSchemaPCustomErr(ctxt,
3207 XML_SCHEMAP_REDEFINED_TYPE,
3208 NULL, NULL, node,
3209 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003210 xmlFree(ret);
3211 return (NULL);
3212 } else {
3213 xmlSchemaTypePtr prev;
3214
3215 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3216 if (prev == NULL) {
3217 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003218 XML_ERR_INTERNAL_ERROR,
3219 "Internal error: xmlSchemaAddType, on type "
3220 "'%s'.\n",
3221 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003222 xmlFree(ret);
3223 return (NULL);
3224 }
3225 ret->redef = prev->redef;
3226 prev->redef = ret;
3227 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003228 }
3229 ret->minOccurs = 1;
3230 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003231 ret->attributeUses = NULL;
3232 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003233 if (ctxt->assemble != NULL)
3234 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003235 return (ret);
3236}
3237
3238/**
3239 * xmlSchemaAddGroup:
3240 * @ctxt: a schema validation context
3241 * @schema: the schema being built
3242 * @name: the group name
3243 *
3244 * Add an XML schema Group definition
3245 *
3246 * Returns the new struture or NULL in case of error
3247 */
3248static xmlSchemaTypePtr
3249xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003250 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003251{
3252 xmlSchemaTypePtr ret = NULL;
3253 int val;
3254
3255 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3256 return (NULL);
3257
3258 if (schema->groupDecl == NULL)
3259 schema->groupDecl = xmlHashCreate(10);
3260 if (schema->groupDecl == NULL)
3261 return (NULL);
3262
3263 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3264 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003265 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003266 return (NULL);
3267 }
3268 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003269 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003270 val =
3271 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3272 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003273 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003274 xmlSchemaPCustomErr(ctxt,
3275 XML_SCHEMAP_REDEFINED_GROUP,
3276 NULL, NULL, node,
3277 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003278 xmlFree(ret);
3279 return (NULL);
3280 }
3281 ret->minOccurs = 1;
3282 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003283 if (ctxt->assemble != NULL)
3284 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003285 return (ret);
3286}
3287
Daniel Veillard3646d642004-06-02 19:19:14 +00003288/**
3289 * xmlSchemaNewWildcardNs:
3290 * @ctxt: a schema validation context
3291 *
3292 * Creates a new wildcard namespace constraint.
3293 *
3294 * Returns the new struture or NULL in case of error
3295 */
3296static xmlSchemaWildcardNsPtr
3297xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3298{
3299 xmlSchemaWildcardNsPtr ret;
3300
3301 ret = (xmlSchemaWildcardNsPtr)
3302 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3303 if (ret == NULL) {
3304 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3305 return (NULL);
3306 }
3307 ret->value = NULL;
3308 ret->next = NULL;
3309 return (ret);
3310}
3311
3312/**
3313 * xmlSchemaAddWildcard:
3314 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003315 * Adds a wildcard. It corresponds to a
3316 * xsd:anyAttribute and is used as storage for namespace
3317 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003318 *
3319 * Returns the new struture or NULL in case of error
3320 */
3321static xmlSchemaWildcardPtr
3322xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3323{
3324 xmlSchemaWildcardPtr ret = NULL;
3325
3326 if (ctxt == NULL)
3327 return (NULL);
3328
3329 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3330 if (ret == NULL) {
3331 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3332 return (NULL);
3333 }
3334 memset(ret, 0, sizeof(xmlSchemaWildcard));
3335 ret->minOccurs = 1;
3336 ret->maxOccurs = 1;
3337
3338 return (ret);
3339}
3340
Daniel Veillard4255d502002-04-16 15:50:10 +00003341/************************************************************************
3342 * *
3343 * Utilities for parsing *
3344 * *
3345 ************************************************************************/
3346
3347/**
3348 * xmlGetQNameProp:
3349 * @ctxt: a schema validation context
3350 * @node: a subtree containing XML Schema informations
3351 * @name: the attribute name
3352 * @namespace: the result namespace if any
3353 *
3354 * Extract a QName Attribute value
3355 *
3356 * Returns the NCName or NULL if not found, and also update @namespace
3357 * with the namespace URI
3358 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003359static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003360xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003361 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003362{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003363 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003364 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003365 const xmlChar *ret, *prefix;
3366 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003367 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003368
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003369 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003370 attr = xmlSchemaGetPropNode(node, name);
3371 if (attr == NULL)
3372 return (NULL);
3373 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003374
Daniel Veillard4255d502002-04-16 15:50:10 +00003375 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003376 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003377
Daniel Veillardba0153a2004-04-01 10:42:31 +00003378 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003379 ns = xmlSearchNs(node->doc, node, 0);
3380 if (ns) {
3381 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3382 return (val);
3383 }
3384 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003385 ret = xmlSplitQName3(val, &len);
3386 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003387 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003388 }
3389 ret = xmlDictLookup(ctxt->dict, ret, -1);
3390 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003391
3392 ns = xmlSearchNs(node->doc, node, prefix);
3393 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003394 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3395 NULL, NULL, (xmlNodePtr) attr,
3396 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003397 "The QName value '%s' has no corresponding namespace "
3398 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003400 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003401 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403}
3404
3405/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003406 * xmlSchemaPValAttrNodeQNameValue:
3407 * @ctxt: a schema parser context
3408 * @schema: the schema context
3409 * @ownerDes: the designation of the parent element
3410 * @ownerItem: the parent as a schema object
3411 * @value: the QName value
3412 * @local: the resulting local part if found, the attribute value otherwise
3413 * @uri: the resulting namespace URI if found
3414 *
3415 * Extracts the local name and the URI of a QName value and validates it.
3416 * This one is intended to be used on attribute values that
3417 * should resolve to schema components.
3418 *
3419 * Returns 0, in case the QName is valid, a positive error code
3420 * if not valid and -1 if an internal error occurs.
3421 */
3422static int
3423xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3424 xmlSchemaPtr schema,
3425 xmlChar **ownerDes,
3426 xmlSchemaTypePtr ownerItem,
3427 xmlAttrPtr attr,
3428 const xmlChar *value,
3429 const xmlChar **uri,
3430 const xmlChar **prefix,
3431 const xmlChar **local)
3432{
3433 const xmlChar *pref;
3434 xmlNsPtr ns;
3435 int len, ret;
3436
3437 *uri = NULL;
3438 *local = NULL;
3439 if (prefix != 0)
3440 *prefix = NULL;
3441 ret = xmlValidateQName(value, 1);
3442 if (ret > 0) {
3443 xmlSchemaPSimpleTypeErr(ctxt,
3444 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3445 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003446 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3447 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003448 NULL, NULL, NULL);
3449 *local = value;
3450 return (ctxt->err);
3451 } else if (ret < 0)
3452 return (-1);
3453
3454 if (!strchr((char *) value, ':')) {
3455 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3456 if (ns)
3457 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3458 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3459 /*
3460 * This one takes care of included schemas with no
3461 * target namespace.
3462 */
3463 *uri = schema->targetNamespace;
3464 }
3465 *local = value;
3466 return (0);
3467 }
3468 /*
3469 * At this point xmlSplitQName3 has to return a local name.
3470 */
3471 *local = xmlSplitQName3(value, &len);
3472 *local = xmlDictLookup(ctxt->dict, *local, -1);
3473 pref = xmlDictLookup(ctxt->dict, value, len);
3474 if (prefix != 0)
3475 *prefix = pref;
3476 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3477 if (ns == NULL) {
3478 xmlSchemaPSimpleTypeErr(ctxt,
3479 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3480 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003481 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3482 "The QName value '%s' has no corresponding namespace "
3483 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003484 return (ctxt->err);
3485 } else {
3486 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3487 }
3488 return (0);
3489}
3490
3491/**
3492 * xmlSchemaPValAttrNodeQName:
3493 * @ctxt: a schema parser context
3494 * @schema: the schema context
3495 * @ownerDes: the designation of the owner element
3496 * @ownerItem: the owner as a schema object
3497 * @attr: the attribute node
3498 * @local: the resulting local part if found, the attribute value otherwise
3499 * @uri: the resulting namespace URI if found
3500 *
3501 * Extracts and validates the QName of an attribute value.
3502 * This one is intended to be used on attribute values that
3503 * should resolve to schema components.
3504 *
3505 * Returns 0, in case the QName is valid, a positive error code
3506 * if not valid and -1 if an internal error occurs.
3507 */
3508static int
3509xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3510 xmlSchemaPtr schema,
3511 xmlChar **ownerDes,
3512 xmlSchemaTypePtr ownerItem,
3513 xmlAttrPtr attr,
3514 const xmlChar **uri,
3515 const xmlChar **prefix,
3516 const xmlChar **local)
3517{
3518 const xmlChar *value;
3519
3520 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3521 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3522 ownerDes, ownerItem, attr, value, uri, prefix, local));
3523}
3524
3525/**
3526 * xmlSchemaPValAttrQName:
3527 * @ctxt: a schema parser context
3528 * @schema: the schema context
3529 * @ownerDes: the designation of the parent element
3530 * @ownerItem: the owner as a schema object
3531 * @ownerElem: the parent node of the attribute
3532 * @name: the name of the attribute
3533 * @local: the resulting local part if found, the attribute value otherwise
3534 * @uri: the resulting namespace URI if found
3535 *
3536 * Extracts and validates the QName of an attribute value.
3537 *
3538 * Returns 0, in case the QName is valid, a positive error code
3539 * if not valid and -1 if an internal error occurs.
3540 */
3541static int
3542xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3543 xmlSchemaPtr schema,
3544 xmlChar **ownerDes,
3545 xmlSchemaTypePtr ownerItem,
3546 xmlNodePtr ownerElem,
3547 const char *name,
3548 const xmlChar **uri,
3549 const xmlChar **prefix,
3550 const xmlChar **local)
3551{
3552 xmlAttrPtr attr;
3553
3554 attr = xmlSchemaGetPropNode(ownerElem, name);
3555 if (attr == NULL) {
3556 *local = NULL;
3557 *uri = NULL;
3558 return (0);
3559 }
3560 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3561 ownerDes, ownerItem, attr, uri, prefix, local));
3562}
3563
3564/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003565 * xmlGetMaxOccurs:
3566 * @ctxt: a schema validation context
3567 * @node: a subtree containing XML Schema informations
3568 *
3569 * Get the maxOccurs property
3570 *
3571 * Returns the default if not found, or the value
3572 */
3573static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003574xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3575 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003576{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003577 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003578 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003579 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003580
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003581 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3582 if (attr == NULL)
3583 return (def);
3584 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003585
3586 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003587 if (max != UNBOUNDED) {
3588 xmlSchemaPSimpleTypeErr(ctxt,
3589 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3590 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3591 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3592 val, NULL, NULL, NULL);
3593 return (def);
3594 } else
3595 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003596 }
3597
3598 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003599 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003600 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003601 if (*cur == 0) {
3602 xmlSchemaPSimpleTypeErr(ctxt,
3603 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3604 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3605 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3606 val, NULL, NULL, NULL);
3607 return (def);
3608 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003610 ret = ret * 10 + (*cur - '0');
3611 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 }
William M. Brack76e95df2003-10-18 16:20:14 +00003613 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003614 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003615 /*
3616 * TODO: Restrict the maximal value to Integer.
3617 */
3618 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3619 xmlSchemaPSimpleTypeErr(ctxt,
3620 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3621 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3622 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3623 val, NULL, NULL, NULL);
3624 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003625 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003626 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003627}
3628
3629/**
3630 * xmlGetMinOccurs:
3631 * @ctxt: a schema validation context
3632 * @node: a subtree containing XML Schema informations
3633 *
3634 * Get the minOccurs property
3635 *
3636 * Returns the default if not found, or the value
3637 */
3638static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003639xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3640 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003642 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003643 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003644 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003645
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003646 attr = xmlSchemaGetPropNode(node, "minOccurs");
3647 if (attr == NULL)
3648 return (def);
3649 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003650 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003651 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003652 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003653 if (*cur == 0) {
3654 xmlSchemaPSimpleTypeErr(ctxt,
3655 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3656 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3657 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3658 val, NULL, NULL, NULL);
3659 return (def);
3660 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003661 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 ret = ret * 10 + (*cur - '0');
3663 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003664 }
William M. Brack76e95df2003-10-18 16:20:14 +00003665 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003666 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003667 /*
3668 * TODO: Restrict the maximal value to Integer.
3669 */
3670 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3671 xmlSchemaPSimpleTypeErr(ctxt,
3672 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3673 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3674 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3675 val, NULL, NULL, NULL);
3676 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003677 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003679}
3680
3681/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003682 * xmlSchemaPGetBoolNodeValue:
3683 * @ctxt: a schema validation context
3684 * @ownerDes: owner designation
3685 * @ownerItem: the owner as a schema item
3686 * @node: the node holding the value
3687 *
3688 * Converts a boolean string value into 1 or 0.
3689 *
3690 * Returns 0 or 1.
3691 */
3692static int
3693xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3694 xmlChar **ownerDes,
3695 xmlSchemaTypePtr ownerItem,
3696 xmlNodePtr node)
3697{
3698 xmlChar *value = NULL;
3699 int res = 0;
3700
3701 value = xmlNodeGetContent(node);
3702 /*
3703 * 3.2.2.1 Lexical representation
3704 * An instance of a datatype that is defined as ·boolean·
3705 * can have the following legal literals {true, false, 1, 0}.
3706 */
3707 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3708 res = 1;
3709 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3710 res = 0;
3711 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3712 res = 1;
3713 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3714 res = 0;
3715 else {
3716 xmlSchemaPSimpleTypeErr(ctxt,
3717 XML_SCHEMAP_INVALID_BOOLEAN,
3718 ownerDes, ownerItem, node,
3719 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3720 "(1 | 0 | true | false)", BAD_CAST value,
3721 NULL, NULL, NULL);
3722 }
3723 if (value != NULL)
3724 xmlFree(value);
3725 return (res);
3726}
3727
3728/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003729 * xmlGetBooleanProp:
3730 * @ctxt: a schema validation context
3731 * @node: a subtree containing XML Schema informations
3732 * @name: the attribute name
3733 * @def: the default value
3734 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003735 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003736 *
3737 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003738 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003739 */
3740static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003741xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3742 xmlChar **ownerDes,
3743 xmlSchemaTypePtr ownerItem,
3744 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003745 const char *name, int def)
3746{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003747 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003748
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003749 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003750 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003751 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003752 /*
3753 * 3.2.2.1 Lexical representation
3754 * An instance of a datatype that is defined as ·boolean·
3755 * can have the following legal literals {true, false, 1, 0}.
3756 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003757 if (xmlStrEqual(val, BAD_CAST "true"))
3758 def = 1;
3759 else if (xmlStrEqual(val, BAD_CAST "false"))
3760 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003761 else if (xmlStrEqual(val, BAD_CAST "1"))
3762 def = 1;
3763 else if (xmlStrEqual(val, BAD_CAST "0"))
3764 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003765 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003766 xmlSchemaPSimpleTypeErr(ctxt,
3767 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003768 ownerDes, ownerItem, node,
3769 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3770 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003771 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003772 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003773}
3774
3775/************************************************************************
3776 * *
3777 * Shema extraction from an Infoset *
3778 * *
3779 ************************************************************************/
3780static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3781 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003782 xmlNodePtr node,
3783 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003784static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3785 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003786 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003787 xmlNodePtr node,
3788 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003789static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3790 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003791 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003792 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003793static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3794 xmlSchemaPtr schema,
3795 xmlNodePtr node);
3796static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3797 xmlSchemaPtr schema,
3798 xmlNodePtr node);
3799static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3800 ctxt,
3801 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003802 xmlNodePtr node,
3803 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003804static xmlSchemaAttributeGroupPtr
3805xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003806 xmlSchemaPtr schema, xmlNodePtr node,
3807 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003808static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3809 xmlSchemaPtr schema,
3810 xmlNodePtr node);
3811static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3812 xmlSchemaPtr schema,
3813 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003814static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003815xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3816 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003817
3818/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003819 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003820 *
3821 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003822 * @ownerDes: the designation of the parent element
3823 * @ownerItem: the schema object owner if existent
3824 * @attr: the schema attribute node being validated
3825 * @value: the value
3826 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003827 *
3828 * Validates a value against the given built-in type.
3829 * This one is intended to be used internally for validation
3830 * of schema attribute values during parsing of the schema.
3831 *
3832 * Returns 0 if the value is valid, a positive error code
3833 * number otherwise and -1 in case of an internal or API error.
3834 */
3835static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003836xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3837 xmlChar **ownerDes,
3838 xmlSchemaTypePtr ownerItem,
3839 xmlAttrPtr attr,
3840 const xmlChar *value,
3841 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003842{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003843
Daniel Veillardc0826a72004-08-10 14:17:33 +00003844 int ret = 0;
3845
3846 /*
3847 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3848 * one is really meant to be used internally, so better not.
3849 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003850 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003851 return (-1);
3852 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3853 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003854 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003855 "Internal error: xmlSchemaPvalueAttrNode, the given "
3856 "type '%s' is not a built-in type.\n",
3857 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003858 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003859 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003860 switch (type->builtInType) {
3861 case XML_SCHEMAS_NCNAME:
3862 ret = xmlValidateNCName(value, 1);
3863 break;
3864 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003865 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003866 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003867 "Internal error: xmlSchemaPvalueAttrNode, use "
3868 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3869 "for extracting QName valueues instead.\n",
3870 NULL, NULL);
3871 return (-1);
3872 case XML_SCHEMAS_ANYURI:
3873 if (value != NULL) {
3874 xmlURIPtr uri = xmlParseURI((const char *) value);
3875 if (uri == NULL)
3876 ret = 1;
3877 else
3878 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003879 }
3880 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003881 case XML_SCHEMAS_TOKEN: {
3882 const xmlChar *cur = value;
3883
3884 if (IS_BLANK_CH(*cur)) {
3885 ret = 1;
3886 } else while (*cur != 0) {
3887 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3888 ret = 1;
3889 break;
3890 } else if (*cur == ' ') {
3891 cur++;
3892 if ((*cur == 0) || (*cur == ' ')) {
3893 ret = 1;
3894 break;
3895 }
3896 } else {
3897 cur++;
3898 }
3899 }
3900 }
3901 break;
3902 case XML_SCHEMAS_LANGUAGE:
3903 if (xmlCheckLanguageID(value) != 1)
3904 ret = 1;
3905 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003906 default: {
3907 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003908 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003909 "Internal error: xmlSchemaPvalueAttrNode, "
3910 "valueidation using the type '%s' is not implemented "
3911 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003912 type->name, NULL);
3913 return (-1);
3914 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003915 }
3916 /*
3917 * TODO: Should we use the S4S error codes instead?
3918 */
3919 if (ret > 0) {
3920 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3921 xmlSchemaPSimpleTypeErr(ctxt,
3922 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3923 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003924 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003925 NULL, NULL, NULL);
3926 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3927 } else {
3928 xmlSchemaPSimpleTypeErr(ctxt,
3929 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3930 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003931 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003932 NULL, NULL, NULL);
3933 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3934 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003935 }
3936 return (ret);
3937}
3938
3939/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003940 * xmlSchemaPValAttrNode:
3941 *
3942 * @ctxt: a schema parser context
3943 * @ownerDes: the designation of the parent element
3944 * @ownerItem: the schema object owner if existent
3945 * @attr: the schema attribute node being validated
3946 * @type: the built-in type to be validated against
3947 * @value: the resulting value if any
3948 *
3949 * Extracts and validates a value against the given built-in type.
3950 * This one is intended to be used internally for validation
3951 * of schema attribute values during parsing of the schema.
3952 *
3953 * Returns 0 if the value is valid, a positive error code
3954 * number otherwise and -1 in case of an internal or API error.
3955 */
3956static int
3957xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3958 xmlChar **ownerDes,
3959 xmlSchemaTypePtr ownerItem,
3960 xmlAttrPtr attr,
3961 xmlSchemaTypePtr type,
3962 const xmlChar **value)
3963{
3964 const xmlChar *val;
3965
3966 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3967 return (-1);
3968
3969 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3970 if (value != NULL)
3971 *value = val;
3972
3973 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3974 val, type));
3975}
3976
3977/**
3978 * xmlSchemaPValAttr:
3979 *
3980 * @ctxt: a schema parser context
3981 * @node: the element node of the attribute
3982 * @ownerDes: the designation of the parent element
3983 * @ownerItem: the schema object owner if existent
3984 * @ownerElem: the owner element node
3985 * @name: the name of the schema attribute node
3986 * @type: the built-in type to be validated against
3987 * @value: the resulting value if any
3988 *
3989 * Extracts and validates a value against the given built-in type.
3990 * This one is intended to be used internally for validation
3991 * of schema attribute values during parsing of the schema.
3992 *
3993 * Returns 0 if the value is valid, a positive error code
3994 * number otherwise and -1 in case of an internal or API error.
3995 */
3996static int
3997xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3998 xmlChar **ownerDes,
3999 xmlSchemaTypePtr ownerItem,
4000 xmlNodePtr ownerElem,
4001 const char *name,
4002 xmlSchemaTypePtr type,
4003 const xmlChar **value)
4004{
4005 xmlAttrPtr attr;
4006
4007 if ((ctxt == NULL) || (type == NULL)) {
4008 if (value != NULL)
4009 *value = NULL;
4010 return (-1);
4011 }
4012 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4013 if (value != NULL)
4014 *value = NULL;
4015 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004016 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004017 "Internal error: xmlSchemaPValAttr, the given "
4018 "type '%s' is not a built-in type.\n",
4019 type->name, NULL);
4020 return (-1);
4021 }
4022 attr = xmlSchemaGetPropNode(ownerElem, name);
4023 if (attr == NULL) {
4024 if (value != NULL)
4025 *value = NULL;
4026 return (0);
4027 }
4028 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4029 type, value));
4030}
4031/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004032 * xmlSchemaParseAttrDecls:
4033 * @ctxt: a schema validation context
4034 * @schema: the schema being built
4035 * @node: a subtree containing XML Schema informations
4036 * @type: the hosting type
4037 *
4038 * parse a XML schema attrDecls declaration corresponding to
4039 * <!ENTITY % attrDecls
4040 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4041 */
4042static xmlNodePtr
4043xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4044 xmlNodePtr child, xmlSchemaTypePtr type)
4045{
4046 xmlSchemaAttributePtr lastattr, attr;
4047
4048 lastattr = NULL;
4049 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004050 (IS_SCHEMA(child, "attributeGroup"))) {
4051 attr = NULL;
4052 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004053 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004054 } else if (IS_SCHEMA(child, "attributeGroup")) {
4055 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004056 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004057 }
4058 if (attr != NULL) {
4059 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004060 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4061 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4062 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004063 type->attributes = attr;
4064 lastattr = attr;
4065 } else {
4066 lastattr->next = attr;
4067 lastattr = attr;
4068 }
4069 }
4070 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004071 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004072 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004073}
4074
4075/**
4076 * xmlSchemaParseAnnotation:
4077 * @ctxt: a schema validation context
4078 * @schema: the schema being built
4079 * @node: a subtree containing XML Schema informations
4080 *
4081 * parse a XML schema Attrribute declaration
4082 * *WARNING* this interface is highly subject to change
4083 *
William M. Bracke7091952004-05-11 15:09:58 +00004084 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 * 1 in case of success.
4086 */
4087static xmlSchemaAnnotPtr
4088xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4089 xmlNodePtr node)
4090{
4091 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004092 xmlNodePtr child = NULL;
4093 xmlAttrPtr attr;
4094 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004095
Daniel Veillardc0826a72004-08-10 14:17:33 +00004096 /*
4097 * INFO: S4S completed.
4098 */
4099 /*
4100 * id = ID
4101 * {any attributes with non-schema namespace . . .}>
4102 * Content: (appinfo | documentation)*
4103 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004104 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4105 return (NULL);
4106 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004107 attr = node->properties;
4108 while (attr != NULL) {
4109 if (((attr->ns == NULL) &&
4110 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4111 ((attr->ns != NULL) &&
4112 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4113
4114 xmlSchemaPIllegalAttrErr(ctxt,
4115 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4116 NULL, NULL, attr);
4117 }
4118 attr = attr->next;
4119 }
4120 /* TODO: Check id. */
4121
4122 /*
4123 * And now for the children...
4124 */
4125 child = node->children;
4126 while (child != NULL) {
4127 if (IS_SCHEMA(child, "appinfo")) {
4128 /* TODO: make available the content of "appinfo". */
4129 /*
4130 * source = anyURI
4131 * {any attributes with non-schema namespace . . .}>
4132 * Content: ({any})*
4133 */
4134 attr = child->properties;
4135 while (attr != NULL) {
4136 if (((attr->ns == NULL) &&
4137 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4138 ((attr->ns != NULL) &&
4139 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004140
Daniel Veillardc0826a72004-08-10 14:17:33 +00004141 xmlSchemaPIllegalAttrErr(ctxt,
4142 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4143 NULL, NULL, attr);
4144 }
4145 attr = attr->next;
4146 }
4147 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4148 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4149 child = child->next;
4150 } else if (IS_SCHEMA(child, "documentation")) {
4151 /* TODO: make available the content of "documentation". */
4152 /*
4153 * source = anyURI
4154 * {any attributes with non-schema namespace . . .}>
4155 * Content: ({any})*
4156 */
4157 attr = child->properties;
4158 while (attr != NULL) {
4159 if (attr->ns == NULL) {
4160 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4161 xmlSchemaPIllegalAttrErr(ctxt,
4162 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4163 NULL, NULL, attr);
4164 }
4165 } else {
4166 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4167 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4168 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4169
4170 xmlSchemaPIllegalAttrErr(ctxt,
4171 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4172 NULL, NULL, attr);
4173 }
4174 }
4175 attr = attr->next;
4176 }
4177 /*
4178 * Attribute "xml:lang".
4179 */
4180 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4181 if (attr != NULL)
4182 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4183 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4184 child = child->next;
4185 } else {
4186 if (!barked)
4187 xmlSchemaPContentErr(ctxt,
4188 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4189 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4190 barked = 1;
4191 child = child->next;
4192 }
4193 }
4194
Daniel Veillard4255d502002-04-16 15:50:10 +00004195 return (ret);
4196}
4197
4198/**
4199 * xmlSchemaParseFacet:
4200 * @ctxt: a schema validation context
4201 * @schema: the schema being built
4202 * @node: a subtree containing XML Schema informations
4203 *
4204 * parse a XML schema Facet declaration
4205 * *WARNING* this interface is highly subject to change
4206 *
4207 * Returns the new type structure or NULL in case of error
4208 */
4209static xmlSchemaFacetPtr
4210xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004211 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004212{
4213 xmlSchemaFacetPtr facet;
4214 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004215 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004216
4217 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4218 return (NULL);
4219
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004220 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004221 if (facet == NULL) {
4222 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4223 return (NULL);
4224 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004225 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004226 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004227 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004228 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4229 "Facet %s has no value\n", node->name, NULL);
4230 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004231 return (NULL);
4232 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004233 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004234 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004235 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004236 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004237 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004238 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004239 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004240 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004241 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004242 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004243 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004244 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004245 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004246 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004249 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004250 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004251 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004252 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004254 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4255 } else if (IS_SCHEMA(node, "minLength")) {
4256 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4257 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004258 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4259 "Unknown facet type %s\n", node->name, NULL);
4260 xmlSchemaFreeFacet(facet);
4261 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004262 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004263 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004264 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004265 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4266 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4267 const xmlChar *fixed;
4268
4269 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4270 if (fixed != NULL) {
4271 if (xmlStrEqual(fixed, BAD_CAST "true"))
4272 facet->fixed = 1;
4273 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004274 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 child = node->children;
4276
4277 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004278 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4279 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 }
4281 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004282 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4283 "Facet %s has unexpected child content\n",
4284 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004285 }
4286 return (facet);
4287}
4288
4289/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004290 * xmlSchemaParseWildcardNs:
4291 * @ctxt: a schema parser context
4292 * @wildc: the wildcard, already created
4293 * @node: a subtree containing XML Schema informations
4294 *
4295 * Parses the attribute "processContents" and "namespace"
4296 * of a xsd:anyAttribute and xsd:any.
4297 * *WARNING* this interface is highly subject to change
4298 *
4299 * Returns 0 if everything goes fine, a positive error code
4300 * if something is not valid and -1 if an internal error occurs.
4301 */
4302static int
4303xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4304 xmlSchemaPtr schema,
4305 xmlSchemaWildcardPtr wildc,
4306 xmlNodePtr node)
4307{
4308 const xmlChar *pc, *ns, *dictnsItem;
4309 int ret = 0;
4310 xmlChar *nsItem;
4311 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4312 xmlAttrPtr attr;
4313
4314 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4315 if ((pc == NULL)
4316 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4317 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4318 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4319 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4320 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4321 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4322 } else {
4323 xmlSchemaPSimpleTypeErr(ctxt,
4324 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4325 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004326 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004327 NULL, NULL, NULL);
4328 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4329 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4330 }
4331 /*
4332 * Build the namespace constraints.
4333 */
4334 attr = xmlSchemaGetPropNode(node, "namespace");
4335 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4336 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4337 wildc->any = 1;
4338 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4339 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4340 if (wildc->negNsSet == NULL) {
4341 return (-1);
4342 }
4343 wildc->negNsSet->value = schema->targetNamespace;
4344 } else {
4345 const xmlChar *end, *cur;
4346
4347 cur = ns;
4348 do {
4349 while (IS_BLANK_CH(*cur))
4350 cur++;
4351 end = cur;
4352 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4353 end++;
4354 if (end == cur)
4355 break;
4356 nsItem = xmlStrndup(cur, end - cur);
4357 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4358 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4359 xmlSchemaPSimpleTypeErr(ctxt,
4360 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4361 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004362 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004363 "((##any | ##other) | List of (anyURI | "
4364 "(##targetNamespace | ##local)))",
4365 nsItem, NULL, NULL, NULL);
4366 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4367 } else {
4368 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4369 dictnsItem = schema->targetNamespace;
4370 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4371 dictnsItem = NULL;
4372 } else {
4373 /*
4374 * Validate the item (anyURI).
4375 */
4376 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4377 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4378 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4379 }
4380 /*
4381 * Avoid dublicate namespaces.
4382 */
4383 tmp = wildc->nsSet;
4384 while (tmp != NULL) {
4385 if (dictnsItem == tmp->value)
4386 break;
4387 tmp = tmp->next;
4388 }
4389 if (tmp == NULL) {
4390 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4391 if (tmp == NULL) {
4392 xmlFree(nsItem);
4393 return (-1);
4394 }
4395 tmp->value = dictnsItem;
4396 tmp->next = NULL;
4397 if (wildc->nsSet == NULL)
4398 wildc->nsSet = tmp;
4399 else
4400 lastNs->next = tmp;
4401 lastNs = tmp;
4402 }
4403
4404 }
4405 xmlFree(nsItem);
4406 cur = end;
4407 } while (*cur != 0);
4408 }
4409 return (ret);
4410}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004411
4412static int
4413xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4414 xmlSchemaTypePtr item,
4415 xmlNodePtr node,
4416 int minOccurs,
4417 int maxOccurs) {
4418
4419 if (maxOccurs != UNBOUNDED) {
4420 /*
4421 * TODO: Maby we should better not create the particle,
4422 * if min/max is invalid, since it could confuse the build of the
4423 * content model.
4424 */
4425 /*
4426 * 3.9.6 Schema Component Constraint: Particle Correct
4427 *
4428 */
4429 if (maxOccurs < 1) {
4430 /*
4431 * 2.2 {max occurs} must be greater than or equal to 1.
4432 */
4433 xmlSchemaPCustomAttrErr(ctxt,
4434 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4435 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4436 "The value must be greater than or equal to 1");
4437 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4438 } else if (minOccurs > maxOccurs) {
4439 /*
4440 * 2.1 {min occurs} must not be greater than {max occurs}.
4441 */
4442 xmlSchemaPCustomAttrErr(ctxt,
4443 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4444 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4445 "The value must not be greater than the value of 'maxOccurs'");
4446 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4447 }
4448 }
4449 return (0);
4450}
4451
Daniel Veillardc0826a72004-08-10 14:17:33 +00004452/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 * xmlSchemaParseAny:
4454 * @ctxt: a schema validation context
4455 * @schema: the schema being built
4456 * @node: a subtree containing XML Schema informations
4457 *
4458 * parse a XML schema Any declaration
4459 * *WARNING* this interface is highly subject to change
4460 *
4461 * Returns the new type structure or NULL in case of error
4462 */
4463static xmlSchemaTypePtr
4464xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4465 xmlNodePtr node)
4466{
4467 xmlSchemaTypePtr type;
4468 xmlNodePtr child = NULL;
4469 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004470 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004471 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004472
4473 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4474 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004475 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4476 "(nonNegativeInteger | unbounded)");
4477 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4478 "nonNegativeInteger");
4479 if ((minOccurs == 0) && (maxOccurs == 0))
4480 return (NULL);
4481
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004482 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004483 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004485 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004486 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004487 type->type = XML_SCHEMA_TYPE_ANY;
4488
Daniel Veillardc0826a72004-08-10 14:17:33 +00004489 wildc = xmlSchemaAddWildcard(ctxt);
4490 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004491 * Check min/max sanity.
4492 */
4493 type->maxOccurs = maxOccurs;
4494 type->minOccurs = minOccurs;
4495 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4496 node, type->minOccurs, type->maxOccurs);
4497 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004498 * This is not nice, since it is won't be used as a attribute wildcard,
4499 * but better than adding a field to the structure.
4500 */
4501 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004502 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004503 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004505 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4506 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004507 }
4508 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004509 xmlSchemaPErr2(ctxt, node, child,
4510 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4511 "Sequence %s has unexpected content\n", type->name,
4512 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004513 }
4514
4515 return (type);
4516}
4517
4518/**
4519 * xmlSchemaParseNotation:
4520 * @ctxt: a schema validation context
4521 * @schema: the schema being built
4522 * @node: a subtree containing XML Schema informations
4523 *
4524 * parse a XML schema Notation declaration
4525 *
4526 * Returns the new structure or NULL in case of error
4527 */
4528static xmlSchemaNotationPtr
4529xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004530 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004531{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004532 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 xmlSchemaNotationPtr ret;
4534 xmlNodePtr child = NULL;
4535
4536 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4537 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004538 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004540 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4541 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004542 return (NULL);
4543 }
4544 ret = xmlSchemaAddNotation(ctxt, schema, name);
4545 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004546 return (NULL);
4547 }
4548 child = node->children;
4549 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004550 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4551 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004552 }
4553 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004554 xmlSchemaPErr2(ctxt, node, child,
4555 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4556 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 }
4558
4559 return (ret);
4560}
4561
4562/**
4563 * xmlSchemaParseAnyAttribute:
4564 * @ctxt: a schema validation context
4565 * @schema: the schema being built
4566 * @node: a subtree containing XML Schema informations
4567 *
4568 * parse a XML schema AnyAttrribute declaration
4569 * *WARNING* this interface is highly subject to change
4570 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004571 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004572 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004573static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004574xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4575 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004576{
Daniel Veillard3646d642004-06-02 19:19:14 +00004577 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004578 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004579 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004580
4581 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4582 return (NULL);
4583
Daniel Veillard3646d642004-06-02 19:19:14 +00004584 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004585 if (ret == NULL) {
4586 return (NULL);
4587 }
William M. Bracke7091952004-05-11 15:09:58 +00004588 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004589 /*
4590 * Check for illegal attributes.
4591 */
4592 attr = node->properties;
4593 while (attr != NULL) {
4594 if (attr->ns == NULL) {
4595 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4596 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4597 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4598 xmlSchemaPIllegalAttrErr(ctxt,
4599 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4600 NULL, NULL, attr);
4601 }
4602 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4603 xmlSchemaPIllegalAttrErr(ctxt,
4604 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4605 NULL, NULL, attr);
4606 }
4607 attr = attr->next;
4608 }
4609 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4610 /*
4611 * Parse the namespace list.
4612 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004613 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4614 xmlSchemaFreeWildcard(ret);
4615 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004616 }
4617 /*
4618 * And now for the children...
4619 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004620 child = node->children;
4621 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004622 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4623 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004624 }
4625 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004626 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004627 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4628 NULL, NULL, node, child,
4629 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 }
4631
4632 return (ret);
4633}
4634
4635
4636/**
4637 * xmlSchemaParseAttribute:
4638 * @ctxt: a schema validation context
4639 * @schema: the schema being built
4640 * @node: a subtree containing XML Schema informations
4641 *
4642 * parse a XML schema Attrribute declaration
4643 * *WARNING* this interface is highly subject to change
4644 *
William M. Bracke7091952004-05-11 15:09:58 +00004645 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004646 */
4647static xmlSchemaAttributePtr
4648xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004649 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004650{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004651 const xmlChar *name, *attrValue;
4652 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004653 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004654 xmlNodePtr child = NULL;
4655 xmlAttrPtr attr, nameAttr;
4656 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004657
4658 /*
4659 * Note that the w3c spec assumes the schema to be validated with schema
4660 * for schemas beforehand.
4661 *
4662 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004663 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004664
4665 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4666 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004667 attr = xmlSchemaGetPropNode(node, "ref");
4668 nameAttr = xmlSchemaGetPropNode(node, "name");
4669
4670 if ((attr == NULL) && (nameAttr == NULL)) {
4671 /*
4672 * 3.2.3 : 3.1
4673 * One of ref or name must be present, but not both
4674 */
4675 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4676 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4677 "One of the attributes 'ref' or 'name' must be present");
4678 return (NULL);
4679 }
4680 if ((topLevel) || (attr == NULL)) {
4681 if (nameAttr == NULL) {
4682 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4683 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4684 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004685 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004686 }
4687 } else
4688 isRef = 1;
4689
4690 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004691 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004692 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4693
4694 /*
4695 * Parse as attribute reference.
4696 */
4697 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4698 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4699 &refPrefix, &ref) != 0) {
4700 return (NULL);
4701 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004702 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004703 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004704 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004705 if (ret == NULL) {
4706 if (repName != NULL)
4707 xmlFree(repName);
4708 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004709 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004710 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4711 ret->node = node;
4712 ret->refNs = refNs;
4713 ret->refPrefix = refPrefix;
4714 ret->ref = ref;
4715 /*
4716 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4717 */
4718 if (nameAttr != NULL)
4719 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4720 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4721 "ref", "name");
4722 /*
4723 * Check for illegal attributes.
4724 */
4725 attr = node->properties;
4726 while (attr != NULL) {
4727 if (attr->ns == NULL) {
4728 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4729 xmlStrEqual(attr->name, BAD_CAST "form")) {
4730 /*
4731 * 3.2.3 : 3.2
4732 * If ref is present, then all of <simpleType>,
4733 * form and type must be absent.
4734 */
4735 xmlSchemaPIllegalAttrErr(ctxt,
4736 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4737 (xmlSchemaTypePtr) ret, attr);
4738 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4739 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4740 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4741 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4742 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4743 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4744 xmlSchemaPIllegalAttrErr(ctxt,
4745 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4746 &repName, (xmlSchemaTypePtr) ret, attr);
4747 }
4748 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4749 xmlSchemaPIllegalAttrErr(ctxt,
4750 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4751 &repName, (xmlSchemaTypePtr) ret, attr);
4752 }
4753 attr = attr->next;
4754 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004755 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004756 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004757
4758 /*
4759 * Parse as attribute declaration.
4760 */
4761 if (xmlSchemaPValAttrNode(ctxt,
4762 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4763 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4764 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004765 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004766 /*
4767 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4768 */
4769 /*
4770 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4771 */
4772 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4773 xmlSchemaPSimpleTypeErr(ctxt,
4774 XML_SCHEMAP_NO_XMLNS,
4775 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004776 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004777 "The value must not match 'xmlns'",
4778 NULL, NULL);
4779 if (repName != NULL)
4780 xmlFree(repName);
4781 return (NULL);
4782 }
4783 /*
4784 * Evaluate the target namespace
4785 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004786 if (topLevel) {
4787 ns = schema->targetNamespace;
4788 } else {
4789 attr = xmlSchemaGetPropNode(node, "form");
4790 if (attr != NULL) {
4791 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4792 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4793 ns = schema->targetNamespace;
4794 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4795 xmlSchemaPSimpleTypeErr(ctxt,
4796 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4797 &repName, NULL, (xmlNodePtr) attr,
4798 NULL, "(qualified | unqualified)",
4799 attrValue, NULL, NULL, NULL);
4800 }
4801 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4802 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004803 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004804 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004805 if (ret == NULL) {
4806 if (repName != NULL)
4807 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004808 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004809 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004810 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4811 ret->node = node;
4812 if (topLevel)
4813 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4814 /*
4815 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4816 */
4817 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4818 xmlSchemaPCustomErr(ctxt,
4819 XML_SCHEMAP_NO_XSI,
4820 &repName, (xmlSchemaTypePtr) ret, node,
4821 "The target namespace must not match '%s'",
4822 xmlSchemaInstanceNs);
4823 }
4824 /*
4825 * Check for illegal attributes.
4826 */
4827 attr = node->properties;
4828 while (attr != NULL) {
4829 if (attr->ns == NULL) {
4830 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4831 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4832 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4833 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4834 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4835 if ((topLevel) ||
4836 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4837 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4838 xmlSchemaPIllegalAttrErr(ctxt,
4839 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4840 &repName, (xmlSchemaTypePtr) ret, attr);
4841 }
4842 }
4843 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4844 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4845 &repName, (xmlSchemaTypePtr) ret, attr);
4846 }
4847 attr = attr->next;
4848 }
4849 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4850 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004851 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004852 /* TODO: Check ID. */
4853 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004854 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004855 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004856 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004857 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4858 if (ret->defValue != NULL)
4859 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4860 /*
4861 * Attribute "default".
4862 */
4863 attr = xmlSchemaGetPropNode(node, "default");
4864 if (attr != NULL) {
4865 /*
4866 * 3.2.3 : 1
4867 * default and fixed must not both be present.
4868 */
4869 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4870 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4871 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4872 } else
4873 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4874 }
4875 if (topLevel == 0) {
4876 /*
4877 * Attribute "use".
4878 */
4879 attr = xmlSchemaGetPropNode(node, "use");
4880 if (attr != NULL) {
4881 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4882 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4883 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4884 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4885 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4886 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4887 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4888 else
4889 xmlSchemaPSimpleTypeErr(ctxt,
4890 XML_SCHEMAP_INVALID_ATTR_USE,
4891 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004892 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004893 attrValue, NULL, NULL, NULL);
4894 } else
4895 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4896 /*
4897 * 3.2.3 : 2
4898 * If default and use are both present, use must have
4899 * the actual value optional.
4900 */
4901 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4902 (ret->defValue != NULL) &&
4903 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4904 xmlSchemaPSimpleTypeErr(ctxt,
4905 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4906 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004907 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004908 "The value must be 'optional' if the attribute "
4909 "'default' is present as well", NULL, NULL);
4910 }
4911 }
4912 /*
4913 * And now for the children...
4914 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004915 child = node->children;
4916 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004917 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4918 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004919 }
4920 if (isRef) {
4921 if (child != NULL) {
4922 if (IS_SCHEMA(child, "simpleType"))
4923 /*
4924 * 3.2.3 : 3.2
4925 * If ref is present, then all of <simpleType>,
4926 * form and type must be absent.
4927 */
4928 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4929 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4930 "(annotation?)");
4931 else
4932 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4933 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4934 "(annotation?)");
4935 }
4936 } else {
4937 if (IS_SCHEMA(child, "simpleType")) {
4938 if (ret->typeName != NULL) {
4939 /*
4940 * 3.2.3 : 4
4941 * type and <simpleType> must not both be present.
4942 */
4943 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4944 &repName, (xmlSchemaTypePtr) ret, node, child,
4945 "The attribute 'type' and the <simpleType> child "
4946 "are mutually exclusive", NULL);
4947 } else
4948 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4949 child = child->next;
4950 }
4951 if (child != NULL)
4952 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4953 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4954 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004955 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004956 /*
4957 * Cleanup.
4958 */
4959 if (repName != NULL)
4960 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004961 return (ret);
4962}
4963
4964/**
4965 * xmlSchemaParseAttributeGroup:
4966 * @ctxt: a schema validation context
4967 * @schema: the schema being built
4968 * @node: a subtree containing XML Schema informations
4969 *
4970 * parse a XML schema Attribute Group declaration
4971 * *WARNING* this interface is highly subject to change
4972 *
4973 * Returns the attribute group or NULL in case of error.
4974 */
4975static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004976xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004977 xmlSchemaPtr schema, xmlNodePtr node,
4978 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004979{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004980 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004981 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004983 const xmlChar *oldcontainer;
4984 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004985
4986 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4987 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004988
4989 nameAttr = xmlSchemaGetPropNode(node, "name");
4990 attr = xmlSchemaGetPropNode(node, "ref");
4991 if ((topLevel) || (attr == NULL)) {
4992 /*
4993 * Parse as an attribute group definition.
4994 * Note that those are allowed at top level only.
4995 */
4996 if (nameAttr == NULL) {
4997 xmlSchemaPMissingAttrErr(ctxt,
4998 XML_SCHEMAP_S4S_ATTR_MISSING,
4999 NULL, NULL, node, "name", NULL);
5000 return (NULL);
5001 }
5002 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5003 /*
5004 * The name is crucial, exit if invalid.
5005 */
5006 if (xmlSchemaPValAttrNode(ctxt,
5007 NULL, NULL, nameAttr,
5008 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5009 return (NULL);
5010 }
5011 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5012 if (ret == NULL)
5013 return (NULL);
5014 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5015 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5016 ret->node = node;
5017 } else {
5018 char buf[50];
5019 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5020
5021 /*
5022 * Parse as an attribute group definition reference.
5023 */
5024 if (attr == NULL) {
5025 xmlSchemaPMissingAttrErr(ctxt,
5026 XML_SCHEMAP_S4S_ATTR_MISSING,
5027 NULL, NULL, node, "ref", NULL);
5028 }
5029 xmlSchemaPValAttrNodeQName(ctxt, schema,
5030 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5031
5032 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5033 name = (const xmlChar *) buf;
5034 if (name == NULL) {
5035 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5036 "attribute group definition reference", node);
5037 return (NULL);
5038 }
5039 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5040 if (ret == NULL)
5041 return (NULL);
5042 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5043 ret->ref = ref;
5044 ret->refNs = refNs;
5045 /* TODO: Is @refPrefix currently used? */
5046 ret->refPrefix = refPrefix;
5047 ret->node = node;
5048 }
5049 /*
5050 * Check for illegal attributes.
5051 */
5052 attr = node->properties;
5053 while (attr != NULL) {
5054 if (attr->ns == NULL) {
5055 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5056 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5057 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5058 {
5059 xmlSchemaPIllegalAttrErr(ctxt,
5060 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5061 NULL, NULL, attr);
5062 }
5063 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5064 xmlSchemaPIllegalAttrErr(ctxt,
5065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5066 NULL, NULL, attr);
5067 }
5068 attr = attr->next;
5069 }
5070 /* TODO: Validate "id" ? */
5071 /*
5072 * And now for the children...
5073 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005074 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005075 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005076 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005077 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005078 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005081 if (topLevel) {
5082 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5083 if (IS_SCHEMA(child, "anyAttribute")) {
5084 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5085 child = child->next;
5086 }
5087 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005088 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005089 xmlSchemaPContentErr(ctxt,
5090 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5091 NULL, NULL, node, child, NULL,
5092 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005093 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005094 ctxt->container = oldcontainer;
5095 return (ret);
5096}
5097
5098/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005099 * xmlSchemaPValAttrFormDefault:
5100 * @value: the value
5101 * @flags: the flags to be modified
5102 * @flagQualified: the specific flag for "qualified"
5103 *
5104 * Returns 0 if the value is valid, 1 otherwise.
5105 */
5106static int
5107xmlSchemaPValAttrFormDefault(const xmlChar *value,
5108 int *flags,
5109 int flagQualified)
5110{
5111 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5112 if ((*flags & flagQualified) == 0)
5113 *flags |= flagQualified;
5114 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5115 return (1);
5116
5117 return (0);
5118}
5119
5120/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005121 * xmlSchemaPValAttrBlockFinal:
5122 * @value: the value
5123 * @flags: the flags to be modified
5124 * @flagAll: the specific flag for "#all"
5125 * @flagExtension: the specific flag for "extension"
5126 * @flagRestriction: the specific flag for "restriction"
5127 * @flagSubstitution: the specific flag for "substitution"
5128 * @flagList: the specific flag for "list"
5129 * @flagUnion: the specific flag for "union"
5130 *
5131 * Validates the value of the attribute "final" and "block". The value
5132 * is converted into the specified flag values and returned in @flags.
5133 *
5134 * Returns 0 if the value is valid, 1 otherwise.
5135 */
5136
5137static int
5138xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5139 int *flags,
5140 int flagAll,
5141 int flagExtension,
5142 int flagRestriction,
5143 int flagSubstitution,
5144 int flagList,
5145 int flagUnion)
5146{
5147 int ret = 0;
5148
5149 /*
5150 * TODO: This does not check for dublicate entries.
5151 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005152 if (value == NULL)
5153 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005154 if (xmlStrEqual(value, BAD_CAST "#all")) {
5155 if (flagAll != -1)
5156 *flags |= flagAll;
5157 else {
5158 if (flagExtension != -1)
5159 *flags |= flagExtension;
5160 if (flagRestriction != -1)
5161 *flags |= flagRestriction;
5162 if (flagSubstitution != -1)
5163 *flags |= flagSubstitution;
5164 if (flagList != -1)
5165 *flags |= flagList;
5166 if (flagUnion != -1)
5167 *flags |= flagUnion;
5168 }
5169 } else {
5170 const xmlChar *end, *cur = value;
5171 xmlChar *item;
5172
5173 do {
5174 while (IS_BLANK_CH(*cur))
5175 cur++;
5176 end = cur;
5177 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5178 end++;
5179 if (end == cur)
5180 break;
5181 item = xmlStrndup(cur, end - cur);
5182 if (xmlStrEqual(item, BAD_CAST "extension")) {
5183 if (flagExtension != -1) {
5184 if ((*flags & flagExtension) == 0)
5185 *flags |= flagExtension;
5186 } else
5187 ret = 1;
5188 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5189 if (flagRestriction != -1) {
5190 if ((*flags & flagRestriction) == 0)
5191 *flags |= flagRestriction;
5192 } else
5193 ret = 1;
5194 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5195 if (flagSubstitution != -1) {
5196 if ((*flags & flagSubstitution) == 0)
5197 *flags |= flagSubstitution;
5198 } else
5199 ret = 1;
5200 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5201 if (flagList != -1) {
5202 if ((*flags & flagList) == 0)
5203 *flags |= flagList;
5204 } else
5205 ret = 1;
5206 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5207 if (flagUnion != -1) {
5208 if ((*flags & flagUnion) == 0)
5209 *flags |= flagUnion;
5210 } else
5211 ret = 1;
5212 } else
5213 ret = 1;
5214 if (item != NULL)
5215 xmlFree(item);
5216 cur = end;
5217 } while ((ret == 0) && (*cur != 0));
5218 }
5219
5220 return (ret);
5221}
5222
5223/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005224 * xmlSchemaParseElement:
5225 * @ctxt: a schema validation context
5226 * @schema: the schema being built
5227 * @node: a subtree containing XML Schema informations
5228 *
5229 * parse a XML schema Element declaration
5230 * *WARNING* this interface is highly subject to change
5231 *
William M. Bracke7091952004-05-11 15:09:58 +00005232 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 */
5234static xmlSchemaElementPtr
5235xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005236 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005237{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005238 const xmlChar *name = NULL;
5239 const xmlChar *attrValue;
5240 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 xmlSchemaElementPtr ret;
5242 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005243 const xmlChar *oldcontainer;
5244 xmlAttrPtr attr, nameAttr;
5245 int minOccurs, maxOccurs;
5246 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005247
5248 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5249 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005250
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5252 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005253
Daniel Veillardc0826a72004-08-10 14:17:33 +00005254 oldcontainer = ctxt->container;
5255
5256 nameAttr = xmlSchemaGetPropNode(node, "name");
5257 attr = xmlSchemaGetPropNode(node, "ref");
5258 if ((topLevel) || (attr == NULL)) {
5259 if (nameAttr == NULL) {
5260 xmlSchemaPMissingAttrErr(ctxt,
5261 XML_SCHEMAP_S4S_ATTR_MISSING,
5262 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5263 "name", NULL);
5264 return (NULL);
5265 }
5266 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5267 } else {
5268 isRef = 1;
5269
5270 }
5271 /*
5272 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5273 * to no component at all
5274 * TODO: It might be better to validate the element, even if it won't be
5275 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005276 */
5277 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5278 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005279 if ((minOccurs == 0) && (maxOccurs == 0))
5280 return (NULL);
5281 /*
5282 * If we get a "ref" attribute on a local <element> we will assume it's
5283 * a reference - even if there's a "name" attribute; this seems to be more
5284 * robust.
5285 */
5286 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005287 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005288 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5289
5290 /*
5291 * Parse as a particle.
5292 */
5293 xmlSchemaPValAttrNodeQName(ctxt, schema,
5294 (xmlChar **) &xmlSchemaElemDesAttrRef,
5295 NULL, attr, &refNs, &refPrefix, &ref);
5296
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005297 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005298 name = (const xmlChar *) buf;
5299 ret = xmlSchemaAddElement(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005300 if (ret == NULL) {
5301 if (repName != NULL)
5302 xmlFree(repName);
5303 return (NULL);
5304 }
5305 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5306 ret->node = node;
5307 ret->ref = ref;
5308 ret->refNs = refNs;
5309 ret->refPrefix = refPrefix;
5310 ret->flags |= XML_SCHEMAS_ELEM_REF;
5311 /*
5312 * Check for illegal attributes.
5313 */
5314 /*
5315 * 3.3.3 : 2.1
5316 * One of ref or name must be present, but not both
5317 */
5318 if (nameAttr != NULL) {
5319 xmlSchemaPMutualExclAttrErr(ctxt,
5320 XML_SCHEMAP_SRC_ELEMENT_2_1,
5321 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5322 "ref", "name");
5323 }
5324 /* 3.3.3 : 2.2 */
5325 attr = node->properties;
5326 while (attr != NULL) {
5327 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005328 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5329 xmlStrEqual(attr->name, BAD_CAST "name") ||
5330 xmlStrEqual(attr->name, BAD_CAST "id") ||
5331 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5332 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5333 {
5334 attr = attr->next;
5335 continue;
5336 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005337 xmlSchemaPCustomAttrErr(ctxt,
5338 XML_SCHEMAP_SRC_ELEMENT_2_2,
5339 &repName, (xmlSchemaTypePtr) ret, attr,
5340 "Only the attributes 'minOccurs', 'maxOccurs' and "
5341 "'id' are allowed in addition to 'ref'");
5342 break;
5343 }
5344 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5345 xmlSchemaPIllegalAttrErr(ctxt,
5346 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5347 &repName, (xmlSchemaTypePtr) ret, attr);
5348 }
5349 attr = attr->next;
5350 }
5351 } else {
5352 const xmlChar *ns = NULL, *fixed;
5353
5354 /*
5355 * Parse as an element declaration.
5356 */
5357 if (xmlSchemaPValAttrNode(ctxt,
5358 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5359 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5360 return (NULL);
5361 /*
5362 * Evaluate the target namespace.
5363 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005364 if (topLevel) {
5365 ns = schema->targetNamespace;
5366 } else {
5367 attr = xmlSchemaGetPropNode(node, "form");
5368 if (attr != NULL) {
5369 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5370 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005371 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005372 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5373 xmlSchemaPSimpleTypeErr(ctxt,
5374 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5375 &repName, NULL, (xmlNodePtr) attr,
5376 NULL, "(qualified | unqualified)",
5377 attrValue, NULL, NULL, NULL);
5378 }
5379 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5380 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005381 }
5382 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005383 if (ret == NULL) {
5384 if (repName != NULL)
5385 xmlFree(repName);
5386 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005387 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005388 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5389 ret->node = node;
5390 /*
5391 * Check for illegal attributes.
5392 */
William M. Bracke7091952004-05-11 15:09:58 +00005393 attr = node->properties;
5394 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005395 if (attr->ns == NULL) {
5396 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5397 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5398 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5399 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5400 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5401 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005402 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5403 {
5404 if (topLevel == 0) {
5405 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005406 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005407 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5408 {
5409 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5410 /*
5411 * 3.3.6 : 3 If there is a non-·absent· {substitution
5412 * group affiliation}, then {scope} must be global.
5413 * TODO: This one is redundant, since the S4S does
5414 * prohibit this attribute on local declarations already;
5415 * so why an explicit error code? Weird spec.
5416 * TODO: Move this to the proper constraint layer.
5417 * TODO: Or better wait for spec 1.1 to come.
5418 */
5419 xmlSchemaPIllegalAttrErr(ctxt,
5420 XML_SCHEMAP_E_PROPS_CORRECT_3,
5421 &repName, (xmlSchemaTypePtr) ret, attr);
5422 } else {
5423 xmlSchemaPIllegalAttrErr(ctxt,
5424 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5425 &repName, (xmlSchemaTypePtr) ret, attr);
5426 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005427 }
5428 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5429 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5430 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5431
5432 xmlSchemaPIllegalAttrErr(ctxt,
5433 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5434 &repName, (xmlSchemaTypePtr) ret, attr);
5435 }
5436 }
5437 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5438
5439 xmlSchemaPIllegalAttrErr(ctxt,
5440 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5441 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005442 }
5443 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005444 }
William M. Bracke7091952004-05-11 15:09:58 +00005445 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005446 * Extract/validate attributes.
5447 */
5448 if (topLevel) {
5449 /*
5450 * Process top attributes of global element declarations here.
5451 */
5452 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5453 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5454 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5455 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5456 &(ret->substGroupNs), NULL, &(ret->substGroup));
5457 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5458 node, "abstract", 0))
5459 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5460 /*
5461 * Attribute "final".
5462 */
5463 attr = xmlSchemaGetPropNode(node, "final");
5464 if (attr == NULL) {
5465 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5466 } else {
5467 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5468 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5469 -1,
5470 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5471 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5472 xmlSchemaPSimpleTypeErr(ctxt,
5473 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5474 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005475 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005476 attrValue, NULL, NULL, NULL);
5477 }
5478 }
5479 }
5480 /*
5481 * Attribute "block".
5482 */
5483 attr = xmlSchemaGetPropNode(node, "block");
5484 if (attr == NULL) {
5485 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5486 } else {
5487 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5488 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5489 -1,
5490 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5491 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5492 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5493 xmlSchemaPSimpleTypeErr(ctxt,
5494 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5495 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005496 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005497 "restriction | substitution))", attrValue,
5498 NULL, NULL, NULL);
5499 }
5500 }
5501 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5502 node, "nillable", 0))
5503 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005504
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 xmlSchemaPValAttrQName(ctxt, schema,
5506 &repName, (xmlSchemaTypePtr) ret, node,
5507 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005508
Daniel Veillardc0826a72004-08-10 14:17:33 +00005509 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5510 attr = xmlSchemaGetPropNode(node, "fixed");
5511 if (attr != NULL) {
5512 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5513 if (ret->value != NULL) {
5514 /*
5515 * 3.3.3 : 1
5516 * default and fixed must not both be present.
5517 */
5518 xmlSchemaPMutualExclAttrErr(ctxt,
5519 XML_SCHEMAP_SRC_ELEMENT_1,
5520 &repName, (xmlSchemaTypePtr) ret, attr,
5521 "default", "fixed");
5522 } else {
5523 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5524 ret->value = fixed;
5525 }
5526 }
5527 }
5528 /*
5529 * Extract/validate common attributes.
5530 */
5531 /* TODO: Check ID: */
5532 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5533 ret->minOccurs = minOccurs;
5534 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005535 if (topLevel != 1)
5536 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5537 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005538 /*
5539 * And now for the children...
5540 */
5541 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005542 child = node->children;
5543 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005544 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5545 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005546 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005547 if (isRef) {
5548 if (child != NULL) {
5549 xmlSchemaPContentErr(ctxt,
5550 XML_SCHEMAP_SRC_ELEMENT_2_2,
5551 &repName, (xmlSchemaTypePtr) ret, node, child,
5552 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005553 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005555 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005556 /*
5557 * 3.3.3 : 3
5558 * "type" and either <simpleType> or <complexType> are mutually
5559 * exclusive
5560 */
William M. Bracke7091952004-05-11 15:09:58 +00005561 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005562 xmlSchemaPContentErr(ctxt,
5563 XML_SCHEMAP_SRC_ELEMENT_3,
5564 &repName, (xmlSchemaTypePtr) ret, node, child,
5565 "The attribute 'type' and the <complexType> child are "
5566 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005567 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005568 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005569 child = child->next;
5570 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005571 /*
5572 * 3.3.3 : 3
5573 * "type" and either <simpleType> or <complexType> are
5574 * mutually exclusive
5575 */
William M. Bracke7091952004-05-11 15:09:58 +00005576 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005577 xmlSchemaPContentErr(ctxt,
5578 XML_SCHEMAP_SRC_ELEMENT_3,
5579 &repName, (xmlSchemaTypePtr) ret, node, child,
5580 "The attribute 'type' and the <simpleType> child are "
5581 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005582 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005583 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005584 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005585 }
William M. Bracke7091952004-05-11 15:09:58 +00005586 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005587 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005588 TODO child = child->next;
5589 }
5590 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005591 xmlSchemaPContentErr(ctxt,
5592 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5593 &repName, (xmlSchemaTypePtr) ret, node, child,
5594 NULL, "(annotation?, ((simpleType | complexType)?, "
5595 "(unique | key | keyref)*))");
5596 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005597
Daniel Veillardc0826a72004-08-10 14:17:33 +00005598 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005599 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005600 /*
5601 * Cleanup.
5602 */
5603 if (repName != NULL)
5604 xmlFree(repName);
5605 /*
5606 * NOTE: Element Declaration Representation OK 4. will be checked at a
5607 * different layer.
5608 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 return (ret);
5610}
5611
5612/**
5613 * xmlSchemaParseUnion:
5614 * @ctxt: a schema validation context
5615 * @schema: the schema being built
5616 * @node: a subtree containing XML Schema informations
5617 *
5618 * parse a XML schema Union definition
5619 * *WARNING* this interface is highly subject to change
5620 *
William M. Bracke7091952004-05-11 15:09:58 +00005621 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005622 * 1 in case of success.
5623 */
5624static xmlSchemaTypePtr
5625xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005627{
5628 xmlSchemaTypePtr type, subtype, last = NULL;
5629 xmlNodePtr child = NULL;
5630 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005631 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005632
5633 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5634 return (NULL);
5635
William M. Brack2f2a6632004-08-20 23:09:47 +00005636 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5637 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005638 if (type == NULL)
5639 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005640 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005641 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005642 /*
5643 * Check for illegal attributes.
5644 */
5645 attr = node->properties;
5646 while (attr != NULL) {
5647 if (attr->ns == NULL) {
5648 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5649 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5650 xmlSchemaPIllegalAttrErr(ctxt,
5651 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5652 NULL, type, attr);
5653 }
5654 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5655 xmlSchemaPIllegalAttrErr(ctxt,
5656 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5657 NULL, type, attr);
5658 }
5659 attr = attr->next;
5660 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005661 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005662 /*
5663 * Attribute "memberTypes". This is a list of QNames.
5664 * TODO: Validate the QNames.
5665 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005666 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005667 /*
5668 * And now for the children...
5669 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005670 child = node->children;
5671 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005672 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5673 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005674 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005675 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005676 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005677 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005678 if (subtype != NULL) {
5679 if (last == NULL) {
5680 type->subtypes = subtype;
5681 last = subtype;
5682 } else {
5683 last->next = subtype;
5684 last = subtype;
5685 }
5686 last->next = NULL;
5687 }
5688 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005689 }
5690 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005691 /* TODO: Think about the error code. */
5692 xmlSchemaPContentErr(ctxt,
5693 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5694 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005695 }
5696 return (type);
5697}
5698
5699/**
5700 * xmlSchemaParseList:
5701 * @ctxt: a schema validation context
5702 * @schema: the schema being built
5703 * @node: a subtree containing XML Schema informations
5704 *
5705 * parse a XML schema List definition
5706 * *WARNING* this interface is highly subject to change
5707 *
William M. Bracke7091952004-05-11 15:09:58 +00005708 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005709 * 1 in case of success.
5710 */
5711static xmlSchemaTypePtr
5712xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005713 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005714{
5715 xmlSchemaTypePtr type, subtype;
5716 xmlNodePtr child = NULL;
5717 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005718 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005719
5720 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5721 return (NULL);
5722
William M. Brack2f2a6632004-08-20 23:09:47 +00005723 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5724 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005725 if (type == NULL)
5726 return (NULL);
5727 type->node = node;
5728 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005729 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005730 /*
5731 * Check for illegal attributes.
5732 */
5733 attr = node->properties;
5734 while (attr != NULL) {
5735 if (attr->ns == NULL) {
5736 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5737 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5738 xmlSchemaPIllegalAttrErr(ctxt,
5739 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5740 NULL, type, attr);
5741 }
5742 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5743 xmlSchemaPIllegalAttrErr(ctxt,
5744 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5745 NULL, type, attr);
5746 }
5747 attr = attr->next;
5748 }
5749 /*
5750 * Attribute "itemType".
5751 */
5752 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5753 node, "itemType", &(type->baseNs), NULL, &(type->base));
5754 /*
5755 * And now for the children...
5756 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005757 child = node->children;
5758 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005759 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5760 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005761 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005762 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005763 if (IS_SCHEMA(child, "simpleType")) {
5764 if (type->base != NULL) {
5765 xmlSchemaPCustomErr(ctxt,
5766 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5767 NULL, type, node,
5768 "The attribute 'itemType' and the <simpleType> child "
5769 "are mutually exclusive", NULL);
5770 } else {
5771 subtype = (xmlSchemaTypePtr)
5772 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5773 type->subtypes = subtype;
5774 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005775 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005776 }
5777 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005778 /* TODO: Think about the error code. */
5779 xmlSchemaPContentErr(ctxt,
5780 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5781 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005782 }
5783 return (type);
5784}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005785
Daniel Veillard4255d502002-04-16 15:50:10 +00005786/**
5787 * xmlSchemaParseSimpleType:
5788 * @ctxt: a schema validation context
5789 * @schema: the schema being built
5790 * @node: a subtree containing XML Schema informations
5791 *
5792 * parse a XML schema Simple Type definition
5793 * *WARNING* this interface is highly subject to change
5794 *
William M. Bracke7091952004-05-11 15:09:58 +00005795 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005796 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005797 */
5798static xmlSchemaTypePtr
5799xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005800 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005801{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005802 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005803 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005804 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005805 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005806 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005807
5808 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5809 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005810
Daniel Veillardc0826a72004-08-10 14:17:33 +00005811 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005812 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005813 if (attr == NULL) {
5814 xmlSchemaPMissingAttrErr(ctxt,
5815 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005816 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005817 "name", NULL);
5818 return (NULL);
5819 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005820 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005821 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005822 return (NULL);
5823 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005824 }
5825
5826 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005827 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005828
Daniel Veillard01fa6152004-06-29 17:04:39 +00005829 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005830 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005831 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005832 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005833 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005834 if (type == NULL)
5835 return (NULL);
5836 type->node = node;
5837 type->type = XML_SCHEMA_TYPE_SIMPLE;
5838 /*
5839 * Check for illegal attributes.
5840 */
5841 attr = node->properties;
5842 while (attr != NULL) {
5843 if (attr->ns == NULL) {
5844 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5845 xmlSchemaPIllegalAttrErr(ctxt,
5846 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005847 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005848 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005849 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5850 xmlSchemaPIllegalAttrErr(ctxt,
5851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005852 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005853 }
5854 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005855 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005856 } else {
5857 /*
5858 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005859 *
5860 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005861 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005862 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005863 if (type == NULL)
5864 return (NULL);
5865 type->node = node;
5866 type->type = XML_SCHEMA_TYPE_SIMPLE;
5867 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5868 /*
5869 * Check for illegal attributes.
5870 */
5871 attr = node->properties;
5872 while (attr != NULL) {
5873 if (attr->ns == NULL) {
5874 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5875 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005876 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005877 xmlSchemaPIllegalAttrErr(ctxt,
5878 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005879 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005880 }
5881 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5882 xmlSchemaPIllegalAttrErr(ctxt,
5883 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005884 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005885 }
5886 attr = attr->next;
5887 }
5888 /*
5889 * Attribute "final".
5890 */
5891 attr = xmlSchemaGetPropNode(node, "final");
5892 if (attr == NULL) {
5893 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5894 } else {
5895 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5896 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5897 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5898 XML_SCHEMAS_TYPE_FINAL_LIST,
5899 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5900
5901 xmlSchemaPSimpleTypeErr(ctxt,
5902 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005903 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005904 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005905 attrValue, NULL, NULL, NULL);
5906 }
5907 }
5908 }
5909 /* TODO: Check id. */
5910 type->id = xmlSchemaGetProp(ctxt, node, "id");
5911 /*
5912 * And now for the children...
5913 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005914 oldCtxtType = ctxt->ctxtType;
5915 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005916 ctxt->ctxtType = type;
5917 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005918 child = node->children;
5919 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005920 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5921 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005922 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005923 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005924 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005925 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005926 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005927 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005928 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005929 subtype = (xmlSchemaTypePtr)
5930 xmlSchemaParseList(ctxt, schema, child);
5931 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005932 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005933 subtype = (xmlSchemaTypePtr)
5934 xmlSchemaParseUnion(ctxt, schema, child);
5935 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005936 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005937 type->subtypes = subtype;
5938 if ((child != NULL) || (subtype == NULL)) {
5939 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005940 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005942 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005943 ctxt->parentItem = oldParentItem;
5944 ctxt->ctxtType = oldCtxtType;
5945 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005946
Daniel Veillard4255d502002-04-16 15:50:10 +00005947 return (type);
5948}
5949
5950
5951/**
5952 * xmlSchemaParseGroup:
5953 * @ctxt: a schema validation context
5954 * @schema: the schema being built
5955 * @node: a subtree containing XML Schema informations
5956 *
5957 * parse a XML schema Group definition
5958 * *WARNING* this interface is highly subject to change
5959 *
William M. Bracke7091952004-05-11 15:09:58 +00005960 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005961 * 1 in case of success.
5962 */
5963static xmlSchemaTypePtr
5964xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005965 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005966{
5967 xmlSchemaTypePtr type, subtype;
5968 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005969 const xmlChar *name;
5970 const xmlChar *ref = NULL, *refNs = NULL;
5971 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005972 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005973
5974 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5975 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005976 /*
5977 * TODO: Validate the element even if no item is created
5978 * (i.e. min/maxOccurs == 0).
5979 */
5980 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5981 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
5982 if ((minOccurs == 0) && (maxOccurs == 0)) {
5983 return (NULL);
5984 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005985 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005986 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005987 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5988 if (ref == NULL) {
5989 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005990 XML_SCHEMAP_GROUP_NONAME_NOREF,
5991 "Group definition or particle: One of the attributes \"name\" "
5992 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005993 return (NULL);
5994 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005995 if (refNs == NULL)
5996 refNs = schema->targetNamespace;
5997 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5998 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006000 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006001 if (type == NULL)
6002 return (NULL);
6003 type->node = node;
6004 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00006005 if (topLevel)
6006 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006007 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006008 type->ref = ref;
6009 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006010 type->minOccurs = minOccurs;
6011 type->maxOccurs = maxOccurs;
6012 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006013 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006014
6015 child = node->children;
6016 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006017 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6018 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006019 }
6020 subtype = NULL;
6021 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006022 subtype = (xmlSchemaTypePtr)
6023 xmlSchemaParseAll(ctxt, schema, child);
6024 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006025 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006026 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6027 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006028 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006029 subtype = (xmlSchemaTypePtr)
6030 xmlSchemaParseSequence(ctxt, schema, child);
6031 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 }
6033 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006035 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006036 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006037 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006039 }
6040
6041 return (type);
6042}
6043
6044/**
6045 * xmlSchemaParseAll:
6046 * @ctxt: a schema validation context
6047 * @schema: the schema being built
6048 * @node: a subtree containing XML Schema informations
6049 *
6050 * parse a XML schema All definition
6051 * *WARNING* this interface is highly subject to change
6052 *
William M. Bracke7091952004-05-11 15:09:58 +00006053 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006054 * 1 in case of success.
6055 */
6056static xmlSchemaTypePtr
6057xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006058 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006059{
6060 xmlSchemaTypePtr type, subtype, last = NULL;
6061 xmlNodePtr child = NULL;
6062 xmlChar name[30];
6063
6064 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6065 return (NULL);
6066
6067
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006068 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006069 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006070 if (type == NULL)
6071 return (NULL);
6072 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006073 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006074 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006075
6076 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6077 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Daniel Veillard4255d502002-04-16 15:50:10 +00006078
6079 child = node->children;
6080 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006081 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6082 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006083 }
6084 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006085 subtype = (xmlSchemaTypePtr)
6086 xmlSchemaParseElement(ctxt, schema, child, 0);
6087 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006088 if (subtype->minOccurs > 1)
6089 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006090 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006091 NULL, NULL);
6092 if (subtype->maxOccurs > 1)
6093 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006094 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006095 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006096 if (last == NULL) {
6097 type->subtypes = subtype;
6098 last = subtype;
6099 } else {
6100 last->next = subtype;
6101 last = subtype;
6102 }
6103 last->next = NULL;
6104 }
6105 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006106 }
6107 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006108 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006109 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006110 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006111 }
6112
6113 return (type);
6114}
6115
6116/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006117 * xmlSchemaCleanupDoc:
6118 * @ctxt: a schema validation context
6119 * @node: the root of the document.
6120 *
6121 * removes unwanted nodes in a schemas document tree
6122 */
6123static void
6124xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6125{
6126 xmlNodePtr delete, cur;
6127
6128 if ((ctxt == NULL) || (root == NULL)) return;
6129
6130 /*
6131 * Remove all the blank text nodes
6132 */
6133 delete = NULL;
6134 cur = root;
6135 while (cur != NULL) {
6136 if (delete != NULL) {
6137 xmlUnlinkNode(delete);
6138 xmlFreeNode(delete);
6139 delete = NULL;
6140 }
6141 if (cur->type == XML_TEXT_NODE) {
6142 if (IS_BLANK_NODE(cur)) {
6143 if (xmlNodeGetSpacePreserve(cur) != 1) {
6144 delete = cur;
6145 }
6146 }
6147 } else if ((cur->type != XML_ELEMENT_NODE) &&
6148 (cur->type != XML_CDATA_SECTION_NODE)) {
6149 delete = cur;
6150 goto skip_children;
6151 }
6152
6153 /*
6154 * Skip to next node
6155 */
6156 if (cur->children != NULL) {
6157 if ((cur->children->type != XML_ENTITY_DECL) &&
6158 (cur->children->type != XML_ENTITY_REF_NODE) &&
6159 (cur->children->type != XML_ENTITY_NODE)) {
6160 cur = cur->children;
6161 continue;
6162 }
6163 }
6164 skip_children:
6165 if (cur->next != NULL) {
6166 cur = cur->next;
6167 continue;
6168 }
6169
6170 do {
6171 cur = cur->parent;
6172 if (cur == NULL)
6173 break;
6174 if (cur == root) {
6175 cur = NULL;
6176 break;
6177 }
6178 if (cur->next != NULL) {
6179 cur = cur->next;
6180 break;
6181 }
6182 } while (cur != NULL);
6183 }
6184 if (delete != NULL) {
6185 xmlUnlinkNode(delete);
6186 xmlFreeNode(delete);
6187 delete = NULL;
6188 }
6189}
6190
William M. Brack2f2a6632004-08-20 23:09:47 +00006191
6192/**
6193 * xmlSchemaImportSchema
6194 *
6195 * @ctxt: a schema validation context
6196 * @schemaLocation: an URI defining where to find the imported schema
6197 *
6198 * import a XML schema
6199 * *WARNING* this interface is highly subject to change
6200 *
6201 * Returns -1 in case of error and 1 in case of success.
6202 */
6203#if 0
6204static xmlSchemaImportPtr
6205xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6206 const xmlChar *schemaLocation)
6207{
6208 xmlSchemaImportPtr import;
6209 xmlSchemaParserCtxtPtr newctxt;
6210
6211 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6212 if (newctxt == NULL) {
6213 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6214 NULL);
6215 return (NULL);
6216 }
6217 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6218 /* Keep the same dictionnary for parsing, really */
6219 xmlDictReference(ctxt->dict);
6220 newctxt->dict = ctxt->dict;
6221 newctxt->includes = 0;
6222 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6223
6224 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6225 ctxt->userData);
6226
6227 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6228 if (import == NULL) {
6229 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6230 NULL);
6231 xmlSchemaFreeParserCtxt(newctxt);
6232 return (NULL);
6233 }
6234
6235 memset(import, 0, sizeof(xmlSchemaImport));
6236 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6237 import->schema = xmlSchemaParse(newctxt);
6238
6239 if (import->schema == NULL) {
6240 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006241 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006242 "Failed to import schema from location \"%s\".\n",
6243 schemaLocation, NULL);
6244
6245 xmlSchemaFreeParserCtxt(newctxt);
6246 /* The schemaLocation is held by the dictionary.
6247 if (import->schemaLocation != NULL)
6248 xmlFree((xmlChar *)import->schemaLocation);
6249 */
6250 xmlFree(import);
6251 return NULL;
6252 }
6253
6254 xmlSchemaFreeParserCtxt(newctxt);
6255 return import;
6256}
6257#endif
6258
6259static void
6260xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6261{
6262 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6263 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6264
6265 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6266 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6267
6268 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6269 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6270 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6271 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6272 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6273 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6274 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6275 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6276
6277 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6278 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6279 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6280 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6281 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6282 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6283}
6284
6285static void
6286xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6287 xmlSchemaPtr schema,
6288 xmlNodePtr node)
6289{
6290 xmlAttrPtr attr;
6291 const xmlChar *val;
6292
6293 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6294 if (attr != NULL) {
6295 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6296 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6297 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6298 xmlSchemaPSimpleTypeErr(ctxt,
6299 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6300 NULL, NULL, (xmlNodePtr) attr, NULL,
6301 "(qualified | unqualified)", val, NULL, NULL, NULL);
6302 }
6303 }
6304
6305 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6306 if (attr != NULL) {
6307 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6308 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6309 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6310 xmlSchemaPSimpleTypeErr(ctxt,
6311 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6312 NULL, NULL, (xmlNodePtr) attr, NULL,
6313 "(qualified | unqualified)", val, NULL, NULL, NULL);
6314 }
6315 }
6316
6317 attr = xmlSchemaGetPropNode(node, "finalDefault");
6318 if (attr != NULL) {
6319 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6320 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6321 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6322 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6323 -1,
6324 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6325 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6326 xmlSchemaPSimpleTypeErr(ctxt,
6327 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6328 NULL, NULL, (xmlNodePtr) attr, NULL,
6329 "(#all | List of (extension | restriction | list | union))",
6330 val, NULL, NULL, NULL);
6331 }
6332 }
6333
6334 attr = xmlSchemaGetPropNode(node, "blockDefault");
6335 if (attr != NULL) {
6336 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6337 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6338 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6339 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6340 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6341 xmlSchemaPSimpleTypeErr(ctxt,
6342 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6343 NULL, NULL, (xmlNodePtr) attr, NULL,
6344 "(#all | List of (extension | restriction | substitution))",
6345 val, NULL, NULL, NULL);
6346 }
6347 }
6348}
6349
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006350/**
6351 * xmlSchemaParseSchemaTopLevel:
6352 * @ctxt: a schema validation context
6353 * @schema: the schemas
6354 * @nodes: the list of top level nodes
6355 *
6356 * Returns the internal XML Schema structure built from the resource or
6357 * NULL in case of error
6358 */
6359static void
6360xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6361 xmlSchemaPtr schema, xmlNodePtr nodes)
6362{
6363 xmlNodePtr child;
6364 xmlSchemaAnnotPtr annot;
6365
6366 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6367 return;
6368
6369 child = nodes;
6370 while ((IS_SCHEMA(child, "include")) ||
6371 (IS_SCHEMA(child, "import")) ||
6372 (IS_SCHEMA(child, "redefine")) ||
6373 (IS_SCHEMA(child, "annotation"))) {
6374 if (IS_SCHEMA(child, "annotation")) {
6375 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6376 if (schema->annot == NULL)
6377 schema->annot = annot;
6378 else
6379 xmlSchemaFreeAnnot(annot);
6380 } else if (IS_SCHEMA(child, "import")) {
6381 xmlSchemaParseImport(ctxt, schema, child);
6382 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006383 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006384 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006385 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006386 } else if (IS_SCHEMA(child, "redefine")) {
6387 TODO
6388 }
6389 child = child->next;
6390 }
6391 while (child != NULL) {
6392 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006393 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006394 child = child->next;
6395 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006396 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006397 child = child->next;
6398 } else if (IS_SCHEMA(child, "element")) {
6399 xmlSchemaParseElement(ctxt, schema, child, 1);
6400 child = child->next;
6401 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006402 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006403 child = child->next;
6404 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006405 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006406 child = child->next;
6407 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006408 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006409 child = child->next;
6410 } else if (IS_SCHEMA(child, "notation")) {
6411 xmlSchemaParseNotation(ctxt, schema, child);
6412 child = child->next;
6413 } else {
6414 xmlSchemaPErr2(ctxt, NULL, child,
6415 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006416 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006417 child->name, NULL);
6418 child = child->next;
6419 }
6420 while (IS_SCHEMA(child, "annotation")) {
6421 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6422 if (schema->annot == NULL)
6423 schema->annot = annot;
6424 else
6425 xmlSchemaFreeAnnot(annot);
6426 child = child->next;
6427 }
6428 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006429 ctxt->parentItem = NULL;
6430 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006431}
6432
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006433static xmlSchemaImportPtr
6434xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6435 xmlHashTablePtr *imports,
6436 const xmlChar *nsName)
6437{
6438 xmlSchemaImportPtr ret;
6439
6440 if (*imports == NULL) {
6441 *imports = xmlHashCreate(10);
6442 if (*imports == NULL) {
6443 xmlSchemaPCustomErr(ctxt,
6444 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6445 NULL, NULL, (xmlNodePtr) ctxt->doc,
6446 "Internal error: failed to build the import table",
6447 NULL);
6448 return (NULL);
6449 }
6450 }
6451 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6452 if (ret == NULL) {
6453 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6454 return (NULL);
6455 }
6456 memset(ret, 0, sizeof(xmlSchemaImport));
6457 if (nsName == NULL)
6458 nsName = XML_SCHEMAS_NO_NAMESPACE;
6459 xmlHashAddEntry(*imports, nsName, ret);
6460
6461 return (ret);
6462}
6463
6464static int
6465xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006466 xmlSchemaPtr schema,
6467 xmlNodePtr node,
6468 const xmlChar *nsName,
6469 const xmlChar *location,
6470 xmlDocPtr *doc,
6471 const xmlChar **targetNamespace,
6472 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006473{
6474 xmlParserCtxtPtr parserCtxt;
6475 xmlSchemaImportPtr import;
6476 const xmlChar *ns;
6477 xmlNodePtr root;
6478
6479 /*
6480 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6481 * <xsi:noNamespaceSchemaLocation>.
6482 */
6483 *doc = NULL;
6484 /*
6485 * Given that the schemaLocation [attribute] is only a hint, it is open
6486 * to applications to ignore all but the first <import> for a given
6487 * namespace, regardless of the ·actual value· of schemaLocation, but
6488 * such a strategy risks missing useful information when new
6489 * schemaLocations are offered.
6490 *
6491 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6492 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6493 * valid or not.
6494 * We will follow XSV here.
6495 */
6496 if (location == NULL) {
6497 /*
6498 * Schema Document Location Strategy:
6499 *
6500 * 3 Based on the namespace name, identify an existing schema document,
6501 * either as a resource which is an XML document or a <schema> element
6502 * information item, in some local schema repository;
6503 *
6504 * 5 Attempt to resolve the namespace name to locate such a resource.
6505 *
6506 * NOTE: Those stategies are not supported, so we will skip.
6507 */
6508 return (0);
6509 }
6510 if (nsName == NULL)
6511 ns = XML_SCHEMAS_NO_NAMESPACE;
6512 else
6513 ns = nsName;
6514
6515 import = xmlHashLookup(schema->schemasImports, ns);
6516 if (import != NULL) {
6517 /*
6518 * There was a valid resource for the specified namespace already
6519 * defined, so skip.
6520 * TODO: This might be changed someday to allow import of
6521 * components from multiple documents for a single target namespace.
6522 */
6523 return (0);
6524 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006525
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006526 /*
6527 * Schema Document Location Strategy:
6528 *
6529 * 2 Based on the location URI, identify an existing schema document,
6530 * either as a resource which is an XML document or a <schema> element
6531 * information item, in some local schema repository;
6532 *
6533 * 4 Attempt to resolve the location URI, to locate a resource on the
6534 * web which is or contains or references a <schema> element;
6535 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6536 *
6537 */
6538 if ((absolute == 0) && (node != NULL)) {
6539 xmlChar *base, *URI;
6540
6541 base = xmlNodeGetBase(node->doc, node);
6542 if (base == NULL) {
6543 URI = xmlBuildURI(location, node->doc->URL);
6544 } else {
6545 URI = xmlBuildURI(location, base);
6546 xmlFree(base);
6547 }
6548 if (URI != NULL) {
6549 location = xmlDictLookup(ctxt->dict, URI, -1);
6550 xmlFree(URI);
6551 }
6552 }
6553 parserCtxt = xmlNewParserCtxt();
6554 if (parserCtxt == NULL) {
6555 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6556 "allocating a parser context", NULL);
6557 return(-1);
6558 }
6559
6560 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6561 NULL, SCHEMAS_PARSE_OPTIONS);
6562
6563 /*
6564 * 2.1 The referent is (a fragment of) a resource which is an
6565 * XML document (see clause 1.1), which in turn corresponds to
6566 * a <schema> element information item in a well-formed information
6567 * set, which in turn corresponds to a valid schema.
6568 * TODO: What to do with the "fragment" stuff?
6569 *
6570 * 2.2 The referent is a <schema> element information item in
6571 * a well-formed information set, which in turn corresponds
6572 * to a valid schema.
6573 * NOTE: 2.2 won't apply, since only XML documents will be processed
6574 * here.
6575 */
6576 if (*doc == NULL) {
6577 xmlErrorPtr lerr;
6578 /*
6579 * It is *not* an error for the application schema reference
6580 * strategy to fail.
6581 *
6582 * If the doc is NULL and the parser error is an IO error we
6583 * will assume that the resource could not be located or accessed.
6584 *
6585 * TODO: Try to find specific error codes to react only on
6586 * localisation failures.
6587 *
6588 * TODO, FIXME: Check the spec: is a namespace added to the imported
6589 * namespaces, even if the schemaLocation did not provide
6590 * a resource? I guess so, since omitting the "schemaLocation"
6591 * attribute, imports a namespace as well.
6592 */
6593 lerr = xmlGetLastError();
6594 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6595 xmlFreeParserCtxt(parserCtxt);
6596 return(0);
6597 }
6598
6599 xmlSchemaPCustomErr(ctxt,
6600 XML_SCHEMAP_SRC_IMPORT_2_1,
6601 NULL, NULL, node,
6602 "Failed to parse the resource '%s' for import",
6603 location);
6604 xmlFreeParserCtxt(parserCtxt);
6605 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6606 }
6607 xmlFreeParserCtxt(parserCtxt);
6608
6609 root = xmlDocGetRootElement(*doc);
6610 if (root == NULL) {
6611 xmlSchemaPCustomErr(ctxt,
6612 XML_SCHEMAP_SRC_IMPORT_2_1,
6613 NULL, NULL, node,
6614 "The XML document '%s' to be imported has no document "
6615 "element", location);
6616 xmlFreeDoc(*doc);
6617 *doc = NULL;
6618 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6619 }
6620
6621 xmlSchemaCleanupDoc(ctxt, root);
6622
6623 if (!IS_SCHEMA(root, "schema")) {
6624 xmlSchemaPCustomErr(ctxt,
6625 XML_SCHEMAP_SRC_IMPORT_2_1,
6626 NULL, NULL, node,
6627 "The XML document '%s' to be imported is not a XML schema document",
6628 location);
6629 xmlFreeDoc(*doc);
6630 *doc = NULL;
6631 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6632 }
6633 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6634 /*
6635 * Schema Representation Constraint: Import Constraints and Semantics
6636 */
6637 if (nsName == NULL) {
6638 if (*targetNamespace != NULL) {
6639 xmlSchemaPCustomErr(ctxt,
6640 XML_SCHEMAP_SRC_IMPORT_3_2,
6641 NULL, NULL, node,
6642 "The XML schema to be imported is not expected "
6643 "to have a target namespace; this differs from "
6644 "its target namespace of '%s'", *targetNamespace);
6645 xmlFreeDoc(*doc);
6646 *doc = NULL;
6647 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6648 }
6649 } else {
6650 if (*targetNamespace == NULL) {
6651 xmlSchemaPCustomErr(ctxt,
6652 XML_SCHEMAP_SRC_IMPORT_3_1,
6653 NULL, NULL, node,
6654 "The XML schema to be imported is expected to have a target "
6655 "namespace of '%s'", nsName);
6656 xmlFreeDoc(*doc);
6657 *doc = NULL;
6658 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6659 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6660 xmlSchemaPCustomErrExt(ctxt,
6661 XML_SCHEMAP_SRC_IMPORT_3_1,
6662 NULL, NULL, node,
6663 "The XML schema to be imported is expected to have a "
6664 "target namespace of '%s'; this differs from "
6665 "its target namespace of '%s'",
6666 nsName, *targetNamespace, NULL);
6667 xmlFreeDoc(*doc);
6668 *doc = NULL;
6669 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6670 }
6671 }
6672
6673 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6674 if (import == NULL) {
6675 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6676 NULL, NULL, NULL,
6677 "Internal error: xmlSchemaAcquireSchemaDoc, "
6678 "failed to build import table", NULL);
6679 xmlFreeDoc(*doc);
6680 *doc = NULL;
6681 return (-1);
6682 }
6683 import->schemaLocation = location;
6684 import->doc = *doc;
6685 return (0);
6686}
William M. Brack2f2a6632004-08-20 23:09:47 +00006687
6688/**
6689 * xmlSchemaParseImport:
6690 * @ctxt: a schema validation context
6691 * @schema: the schema being built
6692 * @node: a subtree containing XML Schema informations
6693 *
6694 * parse a XML schema Import definition
6695 * *WARNING* this interface is highly subject to change
6696 *
6697 * Returns 0 in case of success, a positive error code if
6698 * not valid and -1 in case of an internal error.
6699 */
6700static int
6701xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6702 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006703{
6704 xmlNodePtr child;
6705 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006706 const xmlChar *schemaLocation = NULL;
6707 const xmlChar *targetNamespace, *oldTNS, *url;
6708 xmlAttrPtr attr;
6709 xmlDocPtr doc;
6710 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006711 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006712
6713
6714 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6715 return (-1);
6716
6717 /*
6718 * Check for illegal attributes.
6719 */
6720 attr = node->properties;
6721 while (attr != NULL) {
6722 if (attr->ns == NULL) {
6723 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6724 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6725 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6726 xmlSchemaPIllegalAttrErr(ctxt,
6727 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6728 NULL, NULL, attr);
6729 }
6730 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6731 xmlSchemaPIllegalAttrErr(ctxt,
6732 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6733 NULL, NULL, attr);
6734 }
6735 attr = attr->next;
6736 }
6737 /*
6738 * Extract and validate attributes.
6739 */
6740 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6741 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6742 &namespace) != 0) {
6743 xmlSchemaPSimpleTypeErr(ctxt,
6744 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6745 NULL, NULL, node,
6746 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6747 NULL, namespace, NULL, NULL, NULL);
6748 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6749 }
6750
6751 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6752 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6753 &schemaLocation) != 0) {
6754 xmlSchemaPSimpleTypeErr(ctxt,
6755 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6756 NULL, NULL, node,
6757 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6758 NULL, namespace, NULL, NULL, NULL);
6759 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6760 }
6761 /*
6762 * And now for the children...
6763 */
6764 child = node->children;
6765 if (IS_SCHEMA(child, "annotation")) {
6766 /*
6767 * the annotation here is simply discarded ...
6768 */
6769 child = child->next;
6770 }
6771 if (child != NULL) {
6772 xmlSchemaPContentErr(ctxt,
6773 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6774 NULL, NULL, node, child, NULL,
6775 "(annotation?)");
6776 }
6777 /*
6778 * Apply additional constraints.
6779 */
6780 if (namespace != NULL) {
6781 /*
6782 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6783 * must not match the ·actual value· of the enclosing <schema>'s
6784 * targetNamespace [attribute].
6785 */
6786 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6787 xmlSchemaPCustomErr(ctxt,
6788 XML_SCHEMAP_SRC_IMPORT_1_1,
6789 NULL, NULL, node,
6790 "The value of the attribute 'namespace' must not match "
6791 "the target namespace '%s' of the importing schema",
6792 schema->targetNamespace);
6793 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6794 }
6795 } else {
6796 /*
6797 * 1.2 If the namespace [attribute] is not present, then the enclosing
6798 * <schema> must have a targetNamespace [attribute].
6799 */
6800 if (schema->targetNamespace == NULL) {
6801 xmlSchemaPCustomErr(ctxt,
6802 XML_SCHEMAP_SRC_IMPORT_1_2,
6803 NULL, NULL, node,
6804 "The attribute 'namespace' must be existent if "
6805 "the importing schema has no target namespace",
6806 NULL);
6807 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6808 }
6809 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006810 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006811 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006812 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006813 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6814 schemaLocation, &doc, &targetNamespace, 0);
6815 if (ret != 0) {
6816 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006817 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006818 return (ret);
6819 } else if (doc != NULL) {
6820 /*
6821 * Save and reset the context & schema.
6822 */
6823 url = ctxt->URL;
6824 /* TODO: Is using the doc->URL here correct? */
6825 ctxt->URL = doc->URL;
6826 flags = schema->flags;
6827 oldTNS = schema->targetNamespace;
6828 /*
6829 * Parse the schema.
6830 */
6831 root = xmlDocGetRootElement(doc);
6832 xmlSchemaClearSchemaDefaults(schema);
6833 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6834 schema->targetNamespace = targetNamespace;
6835 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6836 /*
6837 * Restore the context & schema.
6838 */
6839 schema->flags = flags;
6840 schema->targetNamespace = oldTNS;
6841 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00006842 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006843
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006844 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00006845}
6846
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006847/**
6848 * xmlSchemaParseInclude:
6849 * @ctxt: a schema validation context
6850 * @schema: the schema being built
6851 * @node: a subtree containing XML Schema informations
6852 *
6853 * parse a XML schema Include definition
6854 *
William M. Bracke7091952004-05-11 15:09:58 +00006855 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006856 * 1 in case of success.
6857 */
6858static int
6859xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6860 xmlNodePtr node)
6861{
6862 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006863 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006864 xmlDocPtr doc;
6865 xmlNodePtr root;
6866 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006867 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006868 xmlAttrPtr attr;
6869 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006870
6871
6872 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6873 return (-1);
6874
6875 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006876 * Check for illegal attributes.
6877 */
6878 attr = node->properties;
6879 while (attr != NULL) {
6880 if (attr->ns == NULL) {
6881 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6882 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6883 xmlSchemaPIllegalAttrErr(ctxt,
6884 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6885 NULL, NULL, attr);
6886 }
6887 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6888 xmlSchemaPIllegalAttrErr(ctxt,
6889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6890 NULL, NULL, attr);
6891 }
6892 attr = attr->next;
6893 }
6894 /*
6895 * Extract and validate attributes.
6896 */
6897 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006898 * Preliminary step, extract the URI-Reference for the include and
6899 * make an URI from the base.
6900 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006901 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6902 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006903 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006904 xmlChar *uri = NULL;
6905
6906 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6907 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6908 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006909 base = xmlNodeGetBase(node->doc, node);
6910 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006911 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006912 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006913 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006914 xmlFree(base);
6915 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006916 if (uri != NULL) {
6917 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6918 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006919 }
6920 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006921 xmlSchemaPMissingAttrErr(ctxt,
6922 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6923 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006924 return (-1);
6925 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006926 /*
6927 * And now for the children...
6928 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006929 child = node->children;
6930 while (IS_SCHEMA(child, "annotation")) {
6931 /*
6932 * the annotations here are simply discarded ...
6933 */
6934 child = child->next;
6935 }
6936 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006937 xmlSchemaPContentErr(ctxt,
6938 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6939 NULL, NULL, node, child, NULL,
6940 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006941 }
6942
6943 /*
6944 * First step is to parse the input document into an DOM/Infoset
6945 */
6946 doc = xmlReadFile((const char *) schemaLocation, NULL,
6947 SCHEMAS_PARSE_OPTIONS);
6948 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006949 /*
6950 * TODO: It is not an error for the ·actual value· of the
6951 * schemaLocation [attribute] to fail to resolve it all, in which
6952 * case no corresponding inclusion is performed.
6953 * So do we need a warning report here?
6954 */
6955 xmlSchemaPCustomErr(ctxt,
6956 XML_SCHEMAP_FAILED_LOAD,
6957 NULL, NULL, node,
6958 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006959 return(-1);
6960 }
6961
6962 /*
6963 * Then extract the root of the schema
6964 */
6965 root = xmlDocGetRootElement(doc);
6966 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006967 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006968 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006969 NULL, NULL, node,
6970 "The included document '%s' has no document "
6971 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006972 xmlFreeDoc(doc);
6973 return (-1);
6974 }
6975
6976 /*
6977 * Remove all the blank text nodes
6978 */
6979 xmlSchemaCleanupDoc(ctxt, root);
6980
6981 /*
6982 * Check the schemas top level element
6983 */
6984 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006985 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006986 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00006987 NULL, NULL, node,
6988 "The document '%s' to be included is not a schema document",
6989 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006990 xmlFreeDoc(doc);
6991 return (-1);
6992 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006993
William M. Brack2f2a6632004-08-20 23:09:47 +00006994 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006995 /*
6996 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6997 * value· is identical to the ·actual value· of the targetNamespace
6998 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6999 */
7000 if (targetNamespace != NULL) {
7001 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007002 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007003 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007004 NULL, NULL, node,
7005 "The target namespace of the included schema "
7006 "'%s' has to be absent, since the including schema "
7007 "has no target namespace",
7008 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007009 xmlFreeDoc(doc);
7010 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007011 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7012 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007013 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007014 NULL, NULL, node,
7015 "The target namespace '%s' of the included schema '%s' "
7016 "differs from '%s' of the including schema",
7017 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007018 xmlFreeDoc(doc);
7019 return (-1);
7020 }
7021 } else if (schema->targetNamespace != NULL) {
7022 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7023 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7024 } else
7025 wasConvertingNs = 1;
7026 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007027 /*
7028 * register the include
7029 */
7030 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7031 if (include == NULL) {
7032 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7033 xmlFreeDoc(doc);
7034 return (-1);
7035 }
7036
7037 memset(include, 0, sizeof(xmlSchemaInclude));
7038 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7039 include->doc = doc;
7040 include->next = schema->includes;
7041 schema->includes = include;
7042
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007043 /*
7044 * parse the declarations in the included file like if they
7045 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007046 */
7047 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007048 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007049 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007050 /*
7051 * The default values ("blockDefault", "elementFormDefault", etc.)
7052 * are set to the values of the included schema and restored afterwards.
7053 */
7054 saveFlags = schema->flags;
7055 xmlSchemaClearSchemaDefaults(schema);
7056 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007057 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007058 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007059 /*
7060 * Remove the converting flag.
7061 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007062 if ((wasConvertingNs == 0) &&
7063 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007064 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007065 return (1);
7066}
7067
7068/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007069 * xmlSchemaParseChoice:
7070 * @ctxt: a schema validation context
7071 * @schema: the schema being built
7072 * @node: a subtree containing XML Schema informations
7073 *
7074 * parse a XML schema Choice definition
7075 * *WARNING* this interface is highly subject to change
7076 *
William M. Bracke7091952004-05-11 15:09:58 +00007077 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007078 * 1 in case of success.
7079 */
7080static xmlSchemaTypePtr
7081xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007082 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007083{
7084 xmlSchemaTypePtr type, subtype, last = NULL;
7085 xmlNodePtr child = NULL;
7086 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007087 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007088
7089 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7090 return (NULL);
7091
7092
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007093 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007094 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007095 if (type == NULL)
7096 return (NULL);
7097 type->node = node;
7098 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007099 /*
7100 * Check for illegal attributes.
7101 */
7102 attr = node->properties;
7103 while (attr != NULL) {
7104 if (attr->ns == NULL) {
7105 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7106 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7107 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7108 xmlSchemaPIllegalAttrErr(ctxt,
7109 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7110 NULL, type, attr);
7111 }
7112 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7113 xmlSchemaPIllegalAttrErr(ctxt,
7114 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7115 NULL, type, attr);
7116 }
7117 attr = attr->next;
7118 }
7119 /*
7120 * Extract and validate attributes.
7121 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007122 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007123 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7124 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7125 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007126 /*
7127 * And now for the children...
7128 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007129 child = node->children;
7130 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007131 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7132 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007133 }
7134 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007135 (IS_SCHEMA(child, "group")) ||
7136 (IS_SCHEMA(child, "any")) ||
7137 (IS_SCHEMA(child, "choice")) ||
7138 (IS_SCHEMA(child, "sequence"))) {
7139 subtype = NULL;
7140 if (IS_SCHEMA(child, "element")) {
7141 subtype = (xmlSchemaTypePtr)
7142 xmlSchemaParseElement(ctxt, schema, child, 0);
7143 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007144 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007145 } else if (IS_SCHEMA(child, "any")) {
7146 subtype = xmlSchemaParseAny(ctxt, schema, child);
7147 } else if (IS_SCHEMA(child, "sequence")) {
7148 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7149 } else if (IS_SCHEMA(child, "choice")) {
7150 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7151 }
7152 if (subtype != NULL) {
7153 if (last == NULL) {
7154 type->subtypes = subtype;
7155 last = subtype;
7156 } else {
7157 last->next = subtype;
7158 last = subtype;
7159 }
7160 last->next = NULL;
7161 }
7162 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007163 }
7164 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007165 /* TODO: error code. */
7166 xmlSchemaPContentErr(ctxt,
7167 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7168 NULL, type, node, child, NULL,
7169 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007170 }
7171
7172 return (type);
7173}
7174
7175/**
7176 * xmlSchemaParseSequence:
7177 * @ctxt: a schema validation context
7178 * @schema: the schema being built
7179 * @node: a subtree containing XML Schema informations
7180 *
7181 * parse a XML schema Sequence definition
7182 * *WARNING* this interface is highly subject to change
7183 *
William M. Bracke7091952004-05-11 15:09:58 +00007184 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007185 * 1 in case of success.
7186 */
7187static xmlSchemaTypePtr
7188xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007189 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007190{
7191 xmlSchemaTypePtr type, subtype, last = NULL;
7192 xmlNodePtr child = NULL;
7193 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007194 xmlAttrPtr attr;
7195 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007196
7197 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7198 return (NULL);
7199
William M. Brack2f2a6632004-08-20 23:09:47 +00007200 oldcontainer = ctxt->container;
7201 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7202 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007203 if (type == NULL)
7204 return (NULL);
7205 type->node = node;
7206 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007207 /*
7208 * Check for illegal attributes.
7209 */
7210 attr = node->properties;
7211 while (attr != NULL) {
7212 if (attr->ns == NULL) {
7213 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7214 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7215 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7216 xmlSchemaPIllegalAttrErr(ctxt,
7217 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7218 NULL, type, attr);
7219 }
7220 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7221 xmlSchemaPIllegalAttrErr(ctxt,
7222 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7223 NULL, type, attr);
7224 }
7225 attr = attr->next;
7226 }
7227 /*
7228 * Extract and validate attributes.
7229 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007230 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007231 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7232 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7233 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007234 /*
7235 * And now for the children...
7236 */
7237 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007238 child = node->children;
7239 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007240 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7241 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007242 }
7243 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007244 (IS_SCHEMA(child, "group")) ||
7245 (IS_SCHEMA(child, "any")) ||
7246 (IS_SCHEMA(child, "choice")) ||
7247 (IS_SCHEMA(child, "sequence"))) {
7248 subtype = NULL;
7249 if (IS_SCHEMA(child, "element")) {
7250 subtype = (xmlSchemaTypePtr)
7251 xmlSchemaParseElement(ctxt, schema, child, 0);
7252 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007253 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007254 } else if (IS_SCHEMA(child, "any")) {
7255 subtype = xmlSchemaParseAny(ctxt, schema, child);
7256 } else if (IS_SCHEMA(child, "choice")) {
7257 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7258 } else if (IS_SCHEMA(child, "sequence")) {
7259 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7260 }
7261 if (subtype != NULL) {
7262 if (last == NULL) {
7263 type->subtypes = subtype;
7264 last = subtype;
7265 } else {
7266 last->next = subtype;
7267 last = subtype;
7268 }
7269 last->next = NULL;
7270 }
7271 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007272 }
7273 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007274 xmlSchemaPContentErr(ctxt,
7275 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7276 NULL, type, node, child, NULL,
7277 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007278 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007279 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007280
7281 return (type);
7282}
7283
7284/**
7285 * xmlSchemaParseRestriction:
7286 * @ctxt: a schema validation context
7287 * @schema: the schema being built
7288 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007289 *
7290 * parse a XML schema Restriction definition
7291 * *WARNING* this interface is highly subject to change
7292 *
7293 * Returns the type definition or NULL in case of error
7294 */
7295static xmlSchemaTypePtr
7296xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007297 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007298{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007299 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007300 xmlNodePtr child = NULL;
7301 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007302 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007303 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007304
7305 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7306 return (NULL);
7307
7308 oldcontainer = ctxt->container;
7309
William M. Brack2f2a6632004-08-20 23:09:47 +00007310 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7311 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007312 if (type == NULL)
7313 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007314 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007315 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007316 /*
7317 * Check for illegal attributes.
7318 */
7319 attr = node->properties;
7320 while (attr != NULL) {
7321 if (attr->ns == NULL) {
7322 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7323 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7324 xmlSchemaPIllegalAttrErr(ctxt,
7325 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7326 NULL, type, attr);
7327 }
7328 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7329 xmlSchemaPIllegalAttrErr(ctxt,
7330 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7331 NULL, type, attr);
7332 }
7333 attr = attr->next;
7334 }
7335 /*
7336 * Extract and validate attributes.
7337 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007338 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007339 /*
7340 * Attribute "base".
7341 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007342 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007343 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007344 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7345 /* TODO: Think about the error code. */
7346 xmlSchemaPMissingAttrErr(ctxt,
7347 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7348 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007349 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007350 /*
7351 * And now for the children...
7352 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007353 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 child = node->children;
7355 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007356 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7357 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007358 }
7359 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007360 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7361 if (IS_SCHEMA(child, "all")) {
7362 subtype = (xmlSchemaTypePtr)
7363 xmlSchemaParseAll(ctxt, schema, child);
7364 child = child->next;
7365 type->subtypes = subtype;
7366 } else if (IS_SCHEMA(child, "choice")) {
7367 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7368 child = child->next;
7369 type->subtypes = subtype;
7370 } else if (IS_SCHEMA(child, "sequence")) {
7371 subtype = (xmlSchemaTypePtr)
7372 xmlSchemaParseSequence(ctxt, schema, child);
7373 child = child->next;
7374 type->subtypes = subtype;
7375 } else if (IS_SCHEMA(child, "group")) {
7376 subtype = (xmlSchemaTypePtr)
7377 xmlSchemaParseGroup(ctxt, schema, child, 0);
7378 child = child->next;
7379 type->subtypes = subtype;
7380 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007381 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7382 if (IS_SCHEMA(child, "simpleType")) {
7383 if (type->base != NULL) {
7384 /*
7385 * src-restriction-base-or-simpleType
7386 * Either the base [attribute] or the simpleType [child] of the
7387 * <restriction> element must be present, but not both.
7388 */
7389 xmlSchemaPContentErr(ctxt,
7390 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7391 NULL, NULL, type->node, child,
7392 "The attribute 'base' and the <simpleType> child are "
7393 "mutually exclusive", NULL);
7394 } else {
7395 subtype = (xmlSchemaTypePtr)
7396 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7397 type->baseType = subtype;
7398 }
7399 child = child->next;
7400 }
7401 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007402 if (IS_SCHEMA(child, "simpleType")) {
7403 subtype = (xmlSchemaTypePtr)
7404 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007405 type->subtypes = subtype;
7406 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007407 }
7408 }
7409 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7410 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7411 xmlSchemaFacetPtr facet, lastfacet = NULL;
7412
Daniel Veillard01fa6152004-06-29 17:04:39 +00007413 /*
7414 * Add the facets to the parent simpleType/complexType.
7415 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007416 /*
7417 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7418 * Simple Type Definition Schema Representation Constraint:
7419 * *Single Facet Value*
7420 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007421 while ((IS_SCHEMA(child, "minInclusive")) ||
7422 (IS_SCHEMA(child, "minExclusive")) ||
7423 (IS_SCHEMA(child, "maxInclusive")) ||
7424 (IS_SCHEMA(child, "maxExclusive")) ||
7425 (IS_SCHEMA(child, "totalDigits")) ||
7426 (IS_SCHEMA(child, "fractionDigits")) ||
7427 (IS_SCHEMA(child, "pattern")) ||
7428 (IS_SCHEMA(child, "enumeration")) ||
7429 (IS_SCHEMA(child, "whiteSpace")) ||
7430 (IS_SCHEMA(child, "length")) ||
7431 (IS_SCHEMA(child, "maxLength")) ||
7432 (IS_SCHEMA(child, "minLength"))) {
7433 facet = xmlSchemaParseFacet(ctxt, schema, child);
7434 if (facet != NULL) {
7435 if (lastfacet == NULL)
7436 ctxt->ctxtType->facets = facet;
7437 else
7438 lastfacet->next = facet;
7439 lastfacet = facet;
7440 lastfacet->next = NULL;
7441 }
7442 child = child->next;
7443 }
7444 /*
7445 * Create links for derivation and validation.
7446 */
7447 if (lastfacet != NULL) {
7448 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7449
7450 facet = ctxt->ctxtType->facets;
7451 do {
7452 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7453 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007454 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007455 xmlFree(facetLink);
7456 return (NULL);
7457 }
7458 facetLink->facet = facet;
7459 facetLink->next = NULL;
7460 if (lastFacetLink == NULL)
7461 ctxt->ctxtType->facetSet = facetLink;
7462 else
7463 lastFacetLink->next = facetLink;
7464 lastFacetLink = facetLink;
7465 facet = facet->next;
7466 } while (facet != NULL);
7467 }
7468 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007469 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7470 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7471 if (IS_SCHEMA(child, "anyAttribute")) {
7472 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7473 child = child->next;
7474 }
7475 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007476 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007477 /* TODO: Think about the error code. */
7478 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7479 xmlSchemaPContentErr(ctxt,
7480 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7481 NULL, type, node, child, NULL,
7482 "annotation?, (group | all | choice | sequence)?, "
7483 "((attribute | attributeGroup)*, anyAttribute?))");
7484 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7485 xmlSchemaPContentErr(ctxt,
7486 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7487 NULL, type, node, child, NULL,
7488 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7489 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7490 "length | minLength | maxLength | enumeration | whiteSpace | "
7491 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7492 } else {
7493 /* Simple type */
7494 xmlSchemaPContentErr(ctxt,
7495 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7496 NULL, type, node, child, NULL,
7497 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7498 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7499 "length | minLength | maxLength | enumeration | whiteSpace | "
7500 "pattern)*))");
7501 }
7502 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007503 ctxt->container = oldcontainer;
7504 return (type);
7505}
7506
7507/**
7508 * xmlSchemaParseExtension:
7509 * @ctxt: a schema validation context
7510 * @schema: the schema being built
7511 * @node: a subtree containing XML Schema informations
7512 *
7513 * parse a XML schema Extension definition
7514 * *WARNING* this interface is highly subject to change
7515 *
7516 * Returns the type definition or NULL in case of error
7517 */
7518static xmlSchemaTypePtr
7519xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007520 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007521{
7522 xmlSchemaTypePtr type, subtype;
7523 xmlNodePtr child = NULL;
7524 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007525 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007526
7527 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7528 return (NULL);
7529
7530 oldcontainer = ctxt->container;
7531
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007532 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007533 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007534 if (type == NULL)
7535 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007536 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007537 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007538 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007539 ctxt->container = name;
7540
7541 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7542 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007543 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007544 "<extension>: The attribute \"base\" is missing.\n",
7545 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007546 }
7547 child = node->children;
7548 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007549 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7550 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007551 }
7552 subtype = NULL;
7553
7554 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007555 subtype = xmlSchemaParseAll(ctxt, schema, child);
7556 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007557 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007558 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7559 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007560 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007561 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7562 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007563 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007564 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007565 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007566 }
7567 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007568 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007569 if ((ctxt->ctxtType != NULL) &&
7570 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7571 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7572 if (IS_SCHEMA(child, "anyAttribute")) {
7573 ctxt->ctxtType->attributeWildcard =
7574 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7575 child = child->next;
7576 }
7577 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007578 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007579 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007580 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7581 "<extension> has unexpected content.\n", type->name,
7582 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007583 }
7584 ctxt->container = oldcontainer;
7585 return (type);
7586}
7587
7588/**
7589 * xmlSchemaParseSimpleContent:
7590 * @ctxt: a schema validation context
7591 * @schema: the schema being built
7592 * @node: a subtree containing XML Schema informations
7593 *
7594 * parse a XML schema SimpleContent definition
7595 * *WARNING* this interface is highly subject to change
7596 *
7597 * Returns the type definition or NULL in case of error
7598 */
7599static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007600xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7601 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007602{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007603 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007604 xmlNodePtr child = NULL;
7605 xmlChar name[30];
7606
7607 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7608 return (NULL);
7609
William M. Bracke7091952004-05-11 15:09:58 +00007610 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007611 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007612 if (type == NULL)
7613 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007614 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007615 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007616 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007617
7618 child = node->children;
7619 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007620 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7621 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007622 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007623 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007624 ctxt->parentItem = type;
7625 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007626 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007627 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007628 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007629 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007630 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007631 subtype = (xmlSchemaTypePtr)
7632 xmlSchemaParseExtension(ctxt, schema, child);
7633 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007634 }
7635 type->subtypes = subtype;
7636 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007637 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007638 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7639 "<simpleContent> has unexpected content.\n",
7640 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007641 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007642 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007643 return (type);
7644}
7645
7646/**
7647 * xmlSchemaParseComplexContent:
7648 * @ctxt: a schema validation context
7649 * @schema: the schema being built
7650 * @node: a subtree containing XML Schema informations
7651 *
7652 * parse a XML schema ComplexContent definition
7653 * *WARNING* this interface is highly subject to change
7654 *
7655 * Returns the type definition or NULL in case of error
7656 */
7657static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007658xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7659 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007660{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007661 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007662 xmlNodePtr child = NULL;
7663 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007664 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007665
7666 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7667 return (NULL);
7668
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007669 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007670 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007671 if (type == NULL)
7672 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007673 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007674 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007675 /*
7676 * Check for illegal attributes.
7677 */
7678 attr = node->properties;
7679 while (attr != NULL) {
7680 if (attr->ns == NULL) {
7681 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7682 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7683 {
7684 xmlSchemaPIllegalAttrErr(ctxt,
7685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7686 NULL, NULL, attr);
7687 }
7688 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7689 xmlSchemaPIllegalAttrErr(ctxt,
7690 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7691 NULL, NULL, attr);
7692 }
7693 attr = attr->next;
7694 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007695 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007696 /*
7697 * Handle attribute 'mixed'.
7698 */
7699 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7700 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7701 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7702 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007703 child = node->children;
7704 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007705 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7706 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007707 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007708 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007709 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007710 subtype = NULL;
7711 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007712 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007713 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007714 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007715 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007716 subtype = (xmlSchemaTypePtr)
7717 xmlSchemaParseExtension(ctxt, schema, child);
7718 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007719 }
7720 type->subtypes = subtype;
7721 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007722 xmlSchemaPContentErr(ctxt,
7723 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7724 NULL, NULL, node, child,
7725 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007726 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007727 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007728 return (type);
7729}
7730
7731/**
7732 * xmlSchemaParseComplexType:
7733 * @ctxt: a schema validation context
7734 * @schema: the schema being built
7735 * @node: a subtree containing XML Schema informations
7736 *
7737 * parse a XML schema Complex Type definition
7738 * *WARNING* this interface is highly subject to change
7739 *
7740 * Returns the type definition or NULL in case of error
7741 */
7742static xmlSchemaTypePtr
7743xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007744 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007745{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007746 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007747 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007748 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007749 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007750 xmlAttrPtr attr;
7751 const xmlChar *attrValue;
7752 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007753 char buf[40];
7754
Daniel Veillard4255d502002-04-16 15:50:10 +00007755
7756 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7757 return (NULL);
7758
Daniel Veillard01fa6152004-06-29 17:04:39 +00007759 ctxtType = ctxt->ctxtType;
7760
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007761 if (topLevel) {
7762 attr = xmlSchemaGetPropNode(node, "name");
7763 if (attr == NULL) {
7764 xmlSchemaPMissingAttrErr(ctxt,
7765 XML_SCHEMAP_S4S_ATTR_MISSING,
7766 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7767 "name", NULL);
7768 return (NULL);
7769 } else if (xmlSchemaPValAttrNode(ctxt,
7770 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7771 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7772 return (NULL);
7773 }
7774 }
7775
7776 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007777 /*
7778 * Parse as local complex type definition.
7779 */
7780 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7781 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7782 if (type == NULL)
7783 return (NULL);
7784 name = (const xmlChar *) buf;
7785 type->node = node;
7786 type->type = XML_SCHEMA_TYPE_COMPLEX;
7787 /*
7788 * TODO: We need the target namespace.
7789 */
7790 } else {
7791 /*
7792 * Parse as global complex type definition.
7793 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007794 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007795 if (type == NULL)
7796 return (NULL);
7797 type->node = node;
7798 type->type = XML_SCHEMA_TYPE_COMPLEX;
7799 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7800 /*
7801 * Set defaults.
7802 */
7803 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7804 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
7805 }
7806 /*
7807 * Handle attributes.
7808 */
7809 attr = node->properties;
7810 while (attr != NULL) {
7811 if (attr->ns == NULL) {
7812 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7813 /*
7814 * Attribute "id".
7815 */
7816 type->id = xmlSchemaGetProp(ctxt, node, "id");
7817 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
7818 /*
7819 * Attribute "mixed".
7820 */
7821 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7822 (xmlNodePtr) attr))
7823 type->flags |= XML_SCHEMAS_TYPE_MIXED;
7824 } else if (topLevel) {
7825 /*
7826 * Attributes of global complex type definitions.
7827 */
7828 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7829 /* Pass. */
7830 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
7831 /*
7832 * Attribute "abstract".
7833 */
7834 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7835 (xmlNodePtr) attr))
7836 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
7837 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
7838 /*
7839 * Attribute "final".
7840 */
7841 attrValue = xmlSchemaGetNodeContent(ctxt,
7842 (xmlNodePtr) attr);
7843 if (xmlSchemaPValAttrBlockFinal(attrValue,
7844 &(type->flags),
7845 -1,
7846 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
7847 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
7848 -1, -1, -1) != 0)
7849 {
7850 xmlSchemaPSimpleTypeErr(ctxt,
7851 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7852 &des, type, (xmlNodePtr) attr,
7853 NULL,
7854 "(#all | List of (extension | restriction))",
7855 attrValue, NULL, NULL, NULL);
7856 }
7857 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
7858 /*
7859 * Attribute "block".
7860 */
7861 attrValue = xmlSchemaGetNodeContent(ctxt,
7862 (xmlNodePtr) attr);
7863 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7864 -1,
7865 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
7866 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
7867 -1, -1, -1) != 0) {
7868 xmlSchemaPSimpleTypeErr(ctxt,
7869 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7870 &des, type, (xmlNodePtr) attr,
7871 NULL,
7872 "(#all | List of (extension | restriction)) ",
7873 attrValue, NULL, NULL, NULL);
7874 }
7875 } else {
7876 xmlSchemaPIllegalAttrErr(ctxt,
7877 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7878 &des, type, attr);
7879 }
7880 } else {
7881 xmlSchemaPIllegalAttrErr(ctxt,
7882 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7883 &des, type, attr);
7884 }
7885 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7886 xmlSchemaPIllegalAttrErr(ctxt,
7887 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7888 &des, type, attr);
7889 }
7890 attr = attr->next;
7891 }
7892 /*
7893 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007894 * This will be only changed if a complex type
7895 * inherits an attribute wildcard from a base type.
7896 */
7897 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007898 /*
7899 * And now for the children...
7900 */
7901 oldcontainer = ctxt->container;
7902 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007903 child = node->children;
7904 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007905 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7906 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007907 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007908 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007909 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007910 /*
7911 * 3.4.3 : 2.2
7912 * Specifying mixed='true' when the <simpleContent>
7913 * alternative is chosen has no effect
7914 */
William M. Bracke7091952004-05-11 15:09:58 +00007915 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7916 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007917 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7918 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007919 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007920 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7921 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007922 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007923 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007924 /*
7925 * Parse model groups.
7926 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007927 if (IS_SCHEMA(child, "all")) {
7928 subtype = xmlSchemaParseAll(ctxt, schema, child);
7929 child = child->next;
7930 } else if (IS_SCHEMA(child, "choice")) {
7931 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7932 child = child->next;
7933 } else if (IS_SCHEMA(child, "sequence")) {
7934 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7935 child = child->next;
7936 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007937 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007938 child = child->next;
7939 }
7940 if (subtype != NULL)
7941 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007942 /*
7943 * Parse attribute decls/refs.
7944 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007945 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007946 /*
7947 * Parse attribute wildcard.
7948 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007949 if (IS_SCHEMA(child, "anyAttribute")) {
7950 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7951 child = child->next;
7952 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007953 }
7954 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007955 xmlSchemaPContentErr(ctxt,
7956 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7957 &des, type, node, child,
7958 NULL, "(annotation?, (simpleContent | complexContent | "
7959 "((group | all | choice | sequence)?, ((attribute | "
7960 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007961 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007962 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00007963 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007964 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007965 return (type);
7966}
7967
Daniel Veillard4255d502002-04-16 15:50:10 +00007968/**
7969 * xmlSchemaParseSchema:
7970 * @ctxt: a schema validation context
7971 * @node: a subtree containing XML Schema informations
7972 *
7973 * parse a XML schema definition from a node set
7974 * *WARNING* this interface is highly subject to change
7975 *
7976 * Returns the internal XML Schema structure built from the resource or
7977 * NULL in case of error
7978 */
7979static xmlSchemaPtr
7980xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
7981{
7982 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007983 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007984 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007985 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007986
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007987 /*
7988 * This one is called by xmlSchemaParse only and is used if
7989 * the schema to be parsed was specified via the API; i.e. not
7990 * automatically by the validated instance document.
7991 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007992 if ((ctxt == NULL) || (node == NULL))
7993 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007994
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007995 nberrors = ctxt->nberrors;
7996 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007997 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007998 xmlSchemaImportPtr import;
7999
Daniel Veillard4255d502002-04-16 15:50:10 +00008000 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008001 if (schema == NULL)
8002 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008003 /*
8004 * Disable build of list of items.
8005 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008006 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8007 if (attr != NULL) {
8008 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8009 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8010 /*
8011 * TODO: Should we proceed with an invalid target namespace?
8012 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008013 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8014 } else {
8015 schema->targetNamespace = NULL;
8016 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008017 /*
8018 * Add the current ns name and location to the import table;
8019 * this is needed to have a consistent mechanism, regardless
8020 * if all schemata are constructed dynamically fired by the
8021 * instance or if the schema to be used was specified via
8022 * the API.
8023 */
8024 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8025 schema->targetNamespace);
8026 if (import == NULL) {
8027 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8028 NULL, NULL, (xmlNodePtr) ctxt->doc,
8029 "Internal error: xmlSchemaParseSchema, "
8030 "failed to add an import entry", NULL);
8031 xmlSchemaFree(schema);
8032 schema = NULL;
8033 return (NULL);
8034 }
8035 import->schemaLocation = ctxt->URL;
8036 /*
8037 * NOTE: We won't set the doc here, otherwise it will be freed
8038 * if the import struct is freed.
8039 * import->doc = ctxt->doc;
8040 */
8041
Daniel Veillardc0826a72004-08-10 14:17:33 +00008042 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008043 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008044 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8045 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8046
William M. Brack2f2a6632004-08-20 23:09:47 +00008047 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008048 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8049 } else {
8050 xmlDocPtr doc;
8051
8052 doc = node->doc;
8053
8054 if ((doc != NULL) && (doc->URL != NULL)) {
8055 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8056 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008058 } else {
8059 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8060 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008062 }
8063 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008064 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008065 if (ctxt->nberrors != 0) {
8066 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008067 xmlSchemaFree(schema);
8068 schema = NULL;
8069 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008070 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008071 if (schema != NULL)
8072 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008073 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008074#ifdef DEBUG
8075 if (schema == NULL)
8076 xmlGenericError(xmlGenericErrorContext,
8077 "xmlSchemaParse() failed\n");
8078#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008079 return (schema);
8080}
8081
8082/************************************************************************
8083 * *
8084 * Validating using Schemas *
8085 * *
8086 ************************************************************************/
8087
8088/************************************************************************
8089 * *
8090 * Reading/Writing Schemas *
8091 * *
8092 ************************************************************************/
8093
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008094#if 0 /* Will be enabled if it is clear what options are needed. */
8095/**
8096 * xmlSchemaParserCtxtSetOptions:
8097 * @ctxt: a schema parser context
8098 * @options: a combination of xmlSchemaParserOption
8099 *
8100 * Sets the options to be used during the parse.
8101 *
8102 * Returns 0 in case of success, -1 in case of an
8103 * API error.
8104 */
8105static int
8106xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8107 int options)
8108
8109{
8110 int i;
8111
8112 if (ctxt == NULL)
8113 return (-1);
8114 /*
8115 * WARNING: Change the start value if adding to the
8116 * xmlSchemaParseOption.
8117 */
8118 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8119 if (options & 1<<i) {
8120 return (-1);
8121 }
8122 }
8123 ctxt->options = options;
8124 return (0);
8125}
8126
8127/**
8128 * xmlSchemaValidCtxtGetOptions:
8129 * @ctxt: a schema parser context
8130 *
8131 * Returns the option combination of the parser context.
8132 */
8133static int
8134xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8135
8136{
8137 if (ctxt == NULL)
8138 return (-1);
8139 else
8140 return (ctxt->options);
8141}
8142
8143 void *curItems; /* used for dynamic addition of schemata */
8144 int nbCurItems; /* used for dynamic addition of schemata */
8145 int sizeCurItems; /* used for dynamic addition of schemata */
8146
8147#endif
8148
Daniel Veillard4255d502002-04-16 15:50:10 +00008149/**
8150 * xmlSchemaNewParserCtxt:
8151 * @URL: the location of the schema
8152 *
8153 * Create an XML Schemas parse context for that file/resource expected
8154 * to contain an XML Schemas file.
8155 *
8156 * Returns the parser context or NULL in case of error
8157 */
8158xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008159xmlSchemaNewParserCtxt(const char *URL)
8160{
Daniel Veillard4255d502002-04-16 15:50:10 +00008161 xmlSchemaParserCtxtPtr ret;
8162
8163 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008164 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008165
8166 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8167 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008168 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008169 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008170 return (NULL);
8171 }
8172 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008173 ret->dict = xmlDictCreate();
8174 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008175 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008176 return (ret);
8177}
8178
8179/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008180 * xmlSchemaNewParserCtxtUseDict:
8181 * @URL: the location of the schema
8182 * @dict: the dictionary to be used
8183 *
8184 * Create an XML Schemas parse context for that file/resource expected
8185 * to contain an XML Schemas file.
8186 *
8187 * Returns the parser context or NULL in case of error
8188 */
8189static xmlSchemaParserCtxtPtr
8190xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8191{
8192 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008193 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008194 if (URL == NULL)
8195 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008196 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008197
8198 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8199 if (ret == NULL) {
8200 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8201 NULL);
8202 return (NULL);
8203 }
8204 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8205 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008206 xmlDictReference(dict);
8207 if (URL != NULL)
8208 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008209 ret->includes = 0;
8210 return (ret);
8211}
8212
8213
8214/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008215 * xmlSchemaNewMemParserCtxt:
8216 * @buffer: a pointer to a char array containing the schemas
8217 * @size: the size of the array
8218 *
8219 * Create an XML Schemas parse context for that memory buffer expected
8220 * to contain an XML Schemas file.
8221 *
8222 * Returns the parser context or NULL in case of error
8223 */
8224xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008225xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8226{
Daniel Veillard6045c902002-10-09 21:13:59 +00008227 xmlSchemaParserCtxtPtr ret;
8228
8229 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008230 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008231
8232 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8233 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008234 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008235 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008236 return (NULL);
8237 }
8238 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8239 ret->buffer = buffer;
8240 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008241 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008242 return (ret);
8243}
8244
8245/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008246 * xmlSchemaNewDocParserCtxt:
8247 * @doc: a preparsed document tree
8248 *
8249 * Create an XML Schemas parse context for that document.
8250 * NB. The document may be modified during the parsing process.
8251 *
8252 * Returns the parser context or NULL in case of error
8253 */
8254xmlSchemaParserCtxtPtr
8255xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8256{
8257 xmlSchemaParserCtxtPtr ret;
8258
8259 if (doc == NULL)
8260 return (NULL);
8261
8262 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8263 if (ret == NULL) {
8264 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8265 NULL);
8266 return (NULL);
8267 }
8268 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8269 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008270 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008271 /* The application has responsibility for the document */
8272 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008273
8274 return (ret);
8275}
8276
8277/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008278 * xmlSchemaFreeParserCtxt:
8279 * @ctxt: the schema parser context
8280 *
8281 * Free the resources associated to the schema parser context
8282 */
8283void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008284xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8285{
Daniel Veillard4255d502002-04-16 15:50:10 +00008286 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008287 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008288 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008289 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008290 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008291 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008292 xmlFree(ctxt->assemble);
8293 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008294 if (ctxt->vctxt != NULL) {
8295 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8296 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008297 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008298 xmlFree(ctxt);
8299}
8300
8301/************************************************************************
8302 * *
8303 * Building the content models *
8304 * *
8305 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008306
Daniel Veillard4255d502002-04-16 15:50:10 +00008307/**
8308 * xmlSchemaBuildAContentModel:
8309 * @type: the schema type definition
8310 * @ctxt: the schema parser context
8311 * @name: the element name whose content is being built
8312 *
8313 * Generate the automata sequence needed for that type
8314 */
8315static void
8316xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008317 xmlSchemaParserCtxtPtr ctxt,
8318 const xmlChar * name)
8319{
Daniel Veillard4255d502002-04-16 15:50:10 +00008320 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008321 xmlGenericError(xmlGenericErrorContext,
8322 "Found unexpected type = NULL in %s content model\n",
8323 name);
8324 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008325 }
8326 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008327 case XML_SCHEMA_TYPE_ANY: {
8328 xmlAutomataStatePtr start, end;
8329 xmlSchemaWildcardPtr wild;
8330 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008331
Daniel Veillardc0826a72004-08-10 14:17:33 +00008332 wild = type->attributeWildcard;
8333
8334 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008335 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008336 "Internal error: xmlSchemaBuildAContentModel, "
8337 "no wildcard on xsd:any.\n", NULL, NULL);
8338 return;
8339 }
8340
8341 start = ctxt->state;
8342 end = xmlAutomataNewState(ctxt->am);
8343
8344 if (type->maxOccurs == 1) {
8345 if (wild->any == 1) {
8346 /*
8347 * We need to add both transitions:
8348 *
8349 * 1. the {"*", "*"} for elements in a namespace.
8350 */
8351 ctxt->state =
8352 xmlAutomataNewTransition2(ctxt->am,
8353 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8354 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8355 /*
8356 * 2. the {"*"} for elements in no namespace.
8357 */
8358 ctxt->state =
8359 xmlAutomataNewTransition2(ctxt->am,
8360 start, NULL, BAD_CAST "*", NULL, type);
8361 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8362
8363 } else if (wild->nsSet != NULL) {
8364 ns = wild->nsSet;
8365 do {
8366 ctxt->state = start;
8367 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8368 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8369 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8370 ns = ns->next;
8371 } while (ns != NULL);
8372
8373 } else if (wild->negNsSet != NULL) {
8374 xmlAutomataStatePtr deadEnd;
8375
8376 deadEnd = xmlAutomataNewState(ctxt->am);
8377 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8378 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8379 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8380 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8381 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8382 }
8383 } else {
8384 int counter;
8385 xmlAutomataStatePtr hop;
8386 int maxOccurs =
8387 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8388 int minOccurs =
8389 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8390
8391 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8392 hop = xmlAutomataNewState(ctxt->am);
8393 if (wild->any == 1) {
8394 ctxt->state =
8395 xmlAutomataNewTransition2(ctxt->am,
8396 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8397 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8398 ctxt->state =
8399 xmlAutomataNewTransition2(ctxt->am,
8400 start, NULL, BAD_CAST "*", NULL, type);
8401 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8402 } else if (wild->nsSet != NULL) {
8403 ns = wild->nsSet;
8404 do {
8405 ctxt->state =
8406 xmlAutomataNewTransition2(ctxt->am,
8407 start, NULL, BAD_CAST "*", ns->value, type);
8408 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8409 ns = ns->next;
8410 } while (ns != NULL);
8411
8412 } else if (wild->negNsSet != NULL) {
8413 xmlAutomataStatePtr deadEnd;
8414
8415 deadEnd = xmlAutomataNewState(ctxt->am);
8416 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8417 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8418 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8419 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8420 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8421 }
8422 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8423 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8424 }
8425 if (type->minOccurs == 0) {
8426 xmlAutomataNewEpsilon(ctxt->am, start, end);
8427 }
8428 ctxt->state = end;
8429 break;
8430 }
8431 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008432 xmlAutomataStatePtr oldstate;
8433 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008434
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008435 /*
8436 * IMPORTANT: This puts element declarations
8437 * (and never element decl. references) into the
8438 * automaton. This is crucial and should not be changed,
8439 * since validating functions rely now on it.
8440 */
8441 particle = (xmlSchemaElementPtr) type;
8442 if (particle->ref != NULL) {
8443 if (particle->refDecl == NULL) {
8444 /*
8445 * Skip content model creation if the reference
8446 * did not resolve to a declaration.
8447 */
8448 break;
8449 } else {
8450 /*
8451 * Referenced global element declaration.
8452 */
8453 elemDecl = particle->refDecl;
8454 }
8455 } else {
8456 /*
8457 * Anonymous element declaration.
8458 */
8459 elemDecl = particle;
8460 }
8461
8462 oldstate = ctxt->state;
8463
8464 if (particle->maxOccurs >= UNBOUNDED) {
8465 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008466 xmlAutomataStatePtr tmp;
8467 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008468
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008469 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008470 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008471 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008472 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008473 particle->minOccurs - 1, UNBOUNDED);
8474 ctxt->state =
8475 xmlAutomataNewTransition2(ctxt->am,
8476 ctxt->state, NULL,
8477 elemDecl->name,
8478 elemDecl->targetNamespace,
8479 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008480 tmp = ctxt->state;
8481 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008482 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008483 ctxt->state =
8484 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008485 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008486
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008487 } else {
8488 ctxt->state =
8489 xmlAutomataNewTransition2(ctxt->am,
8490 ctxt->state, NULL,
8491 elemDecl->name,
8492 elemDecl->targetNamespace,
8493 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008494 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8495 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008496 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008497 /* basically an elem* */
8498 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8499 ctxt->state);
8500 }
8501 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008502 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008503 xmlAutomataStatePtr tmp;
8504 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008505
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008506 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8507 oldstate, NULL);
8508 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008509 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008510 particle->minOccurs - 1,
8511 particle->maxOccurs - 1);
8512 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8513 ctxt->state,
8514 NULL,
8515 elemDecl->name,
8516 elemDecl->targetNamespace,
8517 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008518 tmp = ctxt->state;
8519 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008520 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008521 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008522 NULL, counter);
8523 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008524 /* basically an elem? */
8525 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008526 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008527 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008528
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008529 } else {
8530 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8531 ctxt->state,
8532 NULL,
8533 elemDecl->name,
8534 elemDecl->targetNamespace,
8535 (xmlSchemaTypePtr) elemDecl);
8536 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008537 /* basically an elem? */
8538 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008539 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008540 }
8541 }
8542 break;
8543 }
8544 case XML_SCHEMA_TYPE_SEQUENCE:{
8545 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008546
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008547 /*
8548 * If max and min occurances are default (1) then
8549 * simply iterate over the subtypes
8550 */
8551 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8552 subtypes = type->subtypes;
8553 while (subtypes != NULL) {
8554 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8555 subtypes = subtypes->next;
8556 }
8557 } else {
8558 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008559
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008560 if (type->maxOccurs >= UNBOUNDED) {
8561 if (type->minOccurs > 1) {
8562 xmlAutomataStatePtr tmp;
8563 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008564
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008565 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8566 oldstate,
8567 NULL);
8568 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008569
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008570 counter = xmlAutomataNewCounter(ctxt->am,
8571 type->
8572 minOccurs - 1,
8573 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008574
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008575 subtypes = type->subtypes;
8576 while (subtypes != NULL) {
8577 xmlSchemaBuildAContentModel(subtypes, ctxt,
8578 name);
8579 subtypes = subtypes->next;
8580 }
8581 tmp = ctxt->state;
8582 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8583 oldstate, counter);
8584 ctxt->state =
8585 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8586 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008587
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008588 } else {
8589 subtypes = type->subtypes;
8590 while (subtypes != NULL) {
8591 xmlSchemaBuildAContentModel(subtypes, ctxt,
8592 name);
8593 subtypes = subtypes->next;
8594 }
8595 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8596 oldstate);
8597 if (type->minOccurs == 0) {
8598 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8599 ctxt->state);
8600 }
8601 }
8602 } else if ((type->maxOccurs > 1)
8603 || (type->minOccurs > 1)) {
8604 xmlAutomataStatePtr tmp;
8605 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008606
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008607 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8608 oldstate,
8609 NULL);
8610 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008611
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008612 counter = xmlAutomataNewCounter(ctxt->am,
8613 type->minOccurs -
8614 1,
8615 type->maxOccurs -
8616 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008617
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008618 subtypes = type->subtypes;
8619 while (subtypes != NULL) {
8620 xmlSchemaBuildAContentModel(subtypes, ctxt,
8621 name);
8622 subtypes = subtypes->next;
8623 }
8624 tmp = ctxt->state;
8625 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8626 counter);
8627 ctxt->state =
8628 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8629 counter);
8630 if (type->minOccurs == 0) {
8631 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8632 ctxt->state);
8633 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008634
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008635 } else {
8636 subtypes = type->subtypes;
8637 while (subtypes != NULL) {
8638 xmlSchemaBuildAContentModel(subtypes, ctxt,
8639 name);
8640 subtypes = subtypes->next;
8641 }
8642 if (type->minOccurs == 0) {
8643 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8644 ctxt->state);
8645 }
8646 }
8647 }
8648 break;
8649 }
8650 case XML_SCHEMA_TYPE_CHOICE:{
8651 xmlSchemaTypePtr subtypes;
8652 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008653
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008654 start = ctxt->state;
8655 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008656
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008657 /*
8658 * iterate over the subtypes and remerge the end with an
8659 * epsilon transition
8660 */
8661 if (type->maxOccurs == 1) {
8662 subtypes = type->subtypes;
8663 while (subtypes != NULL) {
8664 ctxt->state = start;
8665 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8666 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8667 subtypes = subtypes->next;
8668 }
8669 } else {
8670 int counter;
8671 xmlAutomataStatePtr hop;
8672 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8673 UNBOUNDED : type->maxOccurs - 1;
8674 int minOccurs =
8675 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008676
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008677 /*
8678 * use a counter to keep track of the number of transtions
8679 * which went through the choice.
8680 */
8681 counter =
8682 xmlAutomataNewCounter(ctxt->am, minOccurs,
8683 maxOccurs);
8684 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008685
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008686 subtypes = type->subtypes;
8687 while (subtypes != NULL) {
8688 ctxt->state = start;
8689 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8690 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8691 subtypes = subtypes->next;
8692 }
8693 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8694 counter);
8695 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8696 counter);
8697 }
8698 if (type->minOccurs == 0) {
8699 xmlAutomataNewEpsilon(ctxt->am, start, end);
8700 }
8701 ctxt->state = end;
8702 break;
8703 }
8704 case XML_SCHEMA_TYPE_ALL:{
8705 xmlAutomataStatePtr start;
8706 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008707
Daniel Veillard3646d642004-06-02 19:19:14 +00008708 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008709 int lax;
8710
8711 subtypes = type->subtypes;
8712 if (subtypes == NULL)
8713 break;
8714 start = ctxt->state;
8715 while (subtypes != NULL) {
8716 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008717 /*
8718 * the following 'if' was needed to fix bug 139897
8719 * not quite sure why it only needs to be done for
8720 * elements with a 'ref', but it seems to work ok.
8721 */
8722 if (subtypes->ref != NULL)
8723 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008724 elem = (xmlSchemaElementPtr) subtypes;
8725 /*
8726 * NOTE: The {max occurs} of all the particles in the
8727 * {particles} of the group must be 0 or 1.
8728 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008729 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008730 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8731 ctxt->state,
8732 elem->name,
8733 elem->targetNamespace,
8734 1, 1, subtypes);
8735 } else if ((elem->minOccurs == 0) &&
8736 (elem->maxOccurs == 1)) {
8737
8738 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8739 ctxt->state,
8740 elem->name,
8741 elem->targetNamespace,
8742 0,
8743 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008744 subtypes);
8745 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008746 /*
8747 * NOTE: if maxOccurs == 0 then no transition will be
8748 * created.
8749 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008750 subtypes = subtypes->next;
8751 }
8752 lax = type->minOccurs == 0;
8753 ctxt->state =
8754 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8755 lax);
8756 break;
8757 }
8758 case XML_SCHEMA_TYPE_RESTRICTION:
8759 if (type->subtypes != NULL)
8760 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8761 break;
8762 case XML_SCHEMA_TYPE_EXTENSION:
8763 if (type->baseType != NULL) {
8764 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008765
8766 /*
8767 * TODO: Circular definitions will be checked at the
8768 * constraint level. So remove this when the complex type
8769 * constraints are implemented.
8770 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008771 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008772 /* TODO: Change the error code. */
8773 xmlSchemaPCustomErr(ctxt,
8774 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8775 NULL, type, type->node,
8776 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008777 return;
8778 }
8779 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008780 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008781 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008782 subtypes = type->subtypes;
8783 while (subtypes != NULL) {
8784 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8785 subtypes = subtypes->next;
8786 }
8787 } else if (type->subtypes != NULL)
8788 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8789 break;
8790 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008791 /*
8792 * Handle model group definition references.
8793 * NOTE: type->subtypes is the referenced model grop definition;
8794 * and type->subtypes->subtypes is the model group (i.e. <all> or
8795 * <choice> or <sequence>).
8796 */
8797 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8798 (type->subtypes->subtypes != NULL)) {
8799 xmlSchemaTypePtr modelGr;
8800 xmlAutomataStatePtr start, end;
8801
8802 modelGr = type->subtypes->subtypes;
8803 start = ctxt->state;
8804 end = xmlAutomataNewState(ctxt->am);
8805 if (type->maxOccurs == 1) {
8806 ctxt->state = start;
8807 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8808 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8809 } else {
8810 int counter;
8811 xmlAutomataStatePtr hop;
8812 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8813 UNBOUNDED : type->maxOccurs - 1;
8814 int minOccurs =
8815 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8816
8817 counter =
8818 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8819 hop = xmlAutomataNewState(ctxt->am);
8820 ctxt->state = start;
8821 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8822 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8823 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8824 counter);
8825 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8826 counter);
8827 }
8828 if (type->minOccurs == 0) {
8829 xmlAutomataNewEpsilon(ctxt->am, start, end);
8830 }
8831 ctxt->state = end;
8832 break;
8833 }
8834 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008835 case XML_SCHEMA_TYPE_COMPLEX:
8836 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8837 if (type->subtypes != NULL)
8838 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8839 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008840 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8841 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008842 default:
8843 xmlGenericError(xmlGenericErrorContext,
8844 "Found unexpected type %d in %s content model\n",
8845 type->type, name);
8846 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008847 }
8848}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008849
Daniel Veillard4255d502002-04-16 15:50:10 +00008850/**
8851 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008852 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00008853 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008854 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008855 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008856 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00008857 */
8858static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008859xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008860 xmlSchemaParserCtxtPtr ctxt,
8861 const xmlChar * name)
8862{
Daniel Veillard4255d502002-04-16 15:50:10 +00008863 xmlAutomataStatePtr start;
8864
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008865 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
8866 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8867 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
8868 (type->contModel != NULL))
8869 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008870
8871#ifdef DEBUG_CONTENT
8872 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008873 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008874#endif
8875
Daniel Veillard4255d502002-04-16 15:50:10 +00008876 ctxt->am = xmlNewAutomata();
8877 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008878 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008879 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008880 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008881 }
8882 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008883 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008884 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008885 type->contModel = xmlAutomataCompile(ctxt->am);
8886 if (type->contModel == NULL) {
8887 xmlSchemaPCustomErr(ctxt,
8888 XML_SCHEMAP_INTERNAL,
8889 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008890 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008891 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008892 xmlSchemaPCustomErr(ctxt,
8893 XML_SCHEMAP_NOT_DETERMINISTIC,
8894 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008895 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008896 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008897 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008898#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008899 xmlGenericError(xmlGenericErrorContext,
8900 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008901 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008902#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008903 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008904 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008905 xmlFreeAutomata(ctxt->am);
8906 ctxt->am = NULL;
8907}
8908
8909/**
8910 * xmlSchemaRefFixupCallback:
8911 * @elem: the schema element context
8912 * @ctxt: the schema parser context
8913 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008914 * Resolves the references of an element declaration
8915 * or particle, which has an element declaration as it's
8916 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008917 */
8918static void
8919xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008920 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008921 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008922 const xmlChar * context ATTRIBUTE_UNUSED,
8923 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008924{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008925 if ((ctxt == NULL) || (elem == NULL) ||
8926 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008927 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008928 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008929 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008930 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008931
Daniel Veillardc0826a72004-08-10 14:17:33 +00008932 /*
8933 * TODO: Evaluate, what errors could occur if the declaration is not
8934 * found. It might be possible that the "typefixup" might crash if
8935 * no ref declaration was found.
8936 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008937 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008938 if (elemDecl == NULL) {
8939 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008940 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008941 NULL, (xmlSchemaTypePtr) elem, elem->node,
8942 "ref", elem->ref, elem->refNs,
8943 XML_SCHEMA_TYPE_ELEMENT, NULL);
8944 } else
8945 elem->refDecl = elemDecl;
8946 } else {
8947 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8948 xmlSchemaTypePtr type;
8949
8950 /* (type definition) ... otherwise the type definition ·resolved·
8951 * to by the ·actual value· of the type [attribute] ...
8952 */
8953 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8954 elem->namedTypeNs);
8955 if (type == NULL) {
8956 xmlSchemaPResCompAttrErr(ctxt,
8957 XML_SCHEMAP_SRC_RESOLVE,
8958 NULL, (xmlSchemaTypePtr) elem, elem->node,
8959 "type", elem->namedType, elem->namedTypeNs,
8960 XML_SCHEMA_TYPE_BASIC, "type definition");
8961 } else
8962 elem->subtypes = type;
8963 }
8964 if (elem->substGroup != NULL) {
8965 xmlSchemaElementPtr substHead;
8966
8967 /*
8968 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8969 * substitutionGroup?
8970 */
8971 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008972 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008973 if (substHead == NULL) {
8974 xmlSchemaPResCompAttrErr(ctxt,
8975 XML_SCHEMAP_SRC_RESOLVE,
8976 NULL, (xmlSchemaTypePtr) elem, NULL,
8977 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8978 XML_SCHEMA_TYPE_ELEMENT, NULL);
8979 } else {
8980 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
8981 /*
8982 * (type definition)...otherwise the {type definition} of the
8983 * element declaration ·resolved· to by the ·actual value· of
8984 * the substitutionGroup [attribute], if present
8985 */
8986 if (elem->subtypes == NULL)
8987 elem->subtypes = substHead->subtypes;
8988 }
8989 }
8990 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
8991 (elem->substGroup == NULL))
8992 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8993 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008994}
8995
William M. Bracke7091952004-05-11 15:09:58 +00008996/**
8997 * xmlSchemaParseListRefFixup:
8998 * @type: the schema type definition
8999 * @ctxt: the schema parser context
9000 *
9001 * Fixup of the itemType reference of the list type.
9002 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009003static void
William M. Bracke7091952004-05-11 15:09:58 +00009004xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009005{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009006
Daniel Veillard01fa6152004-06-29 17:04:39 +00009007 if (((type->base == NULL) &&
9008 (type->subtypes == NULL)) ||
9009 ((type->base != NULL) &&
9010 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009011 /*
9012 * src-list-itemType-or-simpleType
9013 * Either the itemType [attribute] or the <simpleType> [child] of
9014 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009015 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009016 /*
9017 * TODO: Move this to the parse function.
9018 */
9019 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009020 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009021 NULL, type, type->node,
9022 "The attribute 'itemType' and the <simpleType> child "
9023 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009024 } else if (type->base!= NULL) {
9025 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9026 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009027 xmlSchemaPResCompAttrErr(ctxt,
9028 XML_SCHEMAP_SRC_RESOLVE,
9029 NULL, type, type->node,
9030 "itemType", type->base, type->baseNs,
9031 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009032 }
9033 }
9034 if ((type->subtypes != NULL) &&
9035 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9036 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009037}
9038
9039/**
9040 * xmlSchemaParseUnionRefCheck:
9041 * @typeDecl: the schema type definition
9042 * @ctxt: the schema parser context
9043 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009044 * Checks and builds the memberTypes of the union type.
9045 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009046 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009047static int
William M. Bracke7091952004-05-11 15:09:58 +00009048xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009049 xmlSchemaParserCtxtPtr ctxt)
9050{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009051
Daniel Veillard01fa6152004-06-29 17:04:39 +00009052 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9053 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009054
Daniel Veillard01fa6152004-06-29 17:04:39 +00009055 /* 1 If the <union> alternative is chosen, then [Definition:]
9056 * define the explicit members as the type definitions ·resolved·
9057 * to by the items in the ·actual value· of the memberTypes [attribute],
9058 * if any, followed by the type definitions corresponding to the
9059 * <simpleType>s among the [children] of <union>, if any.
9060 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009061
Daniel Veillard01fa6152004-06-29 17:04:39 +00009062 if (type->type != XML_SCHEMA_TYPE_UNION)
9063 return (-1);
9064 if (ctxt->ctxtType == NULL) {
9065 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009066 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009067 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9068 "available", NULL, NULL);
9069 return (-1);
9070 }
9071 /*
9072 * src-union-memberTypes-or-simpleTypes
9073 * Either the memberTypes [attribute] of the <union> element must
9074 * be non-empty or there must be at least one simpleType [child].
9075 */
9076 if ((type->base == NULL) &&
9077 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009078 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009079 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009080 NULL, NULL, type->node,
9081 "Either the attribute 'memberTypes' must be non-empty "
9082 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009083 }
9084
9085 ctxtType = ctxt->ctxtType;
9086 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009087 xmlAttrPtr attr;
9088 const xmlChar *cur, *end;
9089 xmlChar *tmp;
9090 const xmlChar *localName, *uri;
9091
9092 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009093 cur = type->base;
9094 do {
9095 while (IS_BLANK_CH(*cur))
9096 cur++;
9097 end = cur;
9098 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9099 end++;
9100 if (end == cur)
9101 break;
9102 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009103 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9104 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9105 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009106 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009107 xmlSchemaPResCompAttrErr(ctxt,
9108 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9109 NULL, NULL, type->node, "memberTypes", localName, uri,
9110 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009111 } else {
9112 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9113 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9114 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9115 if (link == NULL) {
9116 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9117 return (-1);
9118 }
9119 link->type = memberType;
9120 link->next = NULL;
9121 if (lastLink == NULL)
9122 ctxtType->memberTypes = link;
9123 else
9124 lastLink->next = link;
9125 lastLink = link;
9126 }
9127 xmlFree(tmp);
9128 cur = end;
9129 } while (*cur != 0);
9130 }
9131 /*
9132 * Add local simple types,
9133 */
9134 memberType = type->subtypes;
9135 while (memberType != NULL) {
9136 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9137 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9138 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9139 if (link == NULL) {
9140 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9141 return (-1);
9142 }
9143 link->type = memberType;
9144 link->next = NULL;
9145 if (lastLink == NULL)
9146 ctxtType->memberTypes = link;
9147 else
9148 lastLink->next = link;
9149 lastLink = link;
9150 memberType = memberType->next;
9151 }
9152 /*
9153 * The actual value is then formed by replacing any union type
9154 * definition in the ·explicit members· with the members of their
9155 * {member type definitions}, in order.
9156 */
9157 link = ctxtType->memberTypes;
9158 while (link != NULL) {
9159 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9160 subLink = link->type->memberTypes;
9161 if (subLink != NULL) {
9162 link->type = subLink->type;
9163 if (subLink->next != NULL) {
9164 lastLink = link->next;
9165 subLink = subLink->next;
9166 prevLink = link;
9167 while (subLink != NULL) {
9168 newLink = (xmlSchemaTypeLinkPtr)
9169 xmlMalloc(sizeof(xmlSchemaTypeLink));
9170 if (newLink == NULL) {
9171 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9172 NULL);
9173 return (-1);
9174 }
9175 newLink->type = memberType;
9176 prevLink->next = newLink;
9177 prevLink = newLink;
9178 newLink->next = lastLink;
9179
9180 subLink = subLink->next;
9181 }
9182 }
9183 }
9184 }
9185 link = link->next;
9186 }
9187
9188 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009189}
9190
Daniel Veillard4255d502002-04-16 15:50:10 +00009191/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009192 * xmlSchemaIsDerivedFromBuiltInType:
9193 * @ctxt: the schema parser context
9194 * @type: the type definition
9195 * @valType: the value type
9196 *
9197 *
9198 * Returns 1 if the type has the given value type, or
9199 * is derived from such a type.
9200 */
William M. Brack803812b2004-06-03 02:11:24 +00009201static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009202xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9203 xmlSchemaTypePtr type, int valType)
9204{
9205 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009206 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009207 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009208 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009209 return(1);
9210 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9211 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9212 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9213 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9214 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9215 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9216 if (type->baseType != NULL)
9217 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9218 valType));
9219 } else if ((type->subtypes != NULL) &&
9220 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9221 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9222 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9223 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9224 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9225 valType));
9226 }
9227
9228 return (0);
9229}
9230
9231/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009232 * xmlSchemaIsDerivedFromBuiltInType:
9233 * @type: the simpleType definition
9234 *
9235 * Returns the primitive type of the given type or
9236 * NULL in case of error.
9237 */
9238static xmlSchemaTypePtr
9239xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9240{
9241 while (type != NULL) {
9242 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9243 return (type);
9244 type = type->baseType;
9245 }
9246
9247 return (NULL);
9248}
9249
9250
9251/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009252 * xmlSchemaBuildAttributeUsesOwned:
9253 * @ctxt: the schema parser context
9254 * @type: the complex type definition
9255 * @cur: the attribute declaration list
9256 * @lastUse: the top of the attribute use list
9257 *
9258 * Builds the attribute uses list on the given complex type.
9259 * This one is supposed to be called by
9260 * xmlSchemaBuildAttributeValidation only.
9261 */
9262static int
9263xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9264 xmlSchemaAttributePtr cur,
9265 xmlSchemaAttributeLinkPtr *uses,
9266 xmlSchemaAttributeLinkPtr *lastUse)
9267{
9268 xmlSchemaAttributeLinkPtr tmp;
9269 while (cur != NULL) {
9270 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9271 /*
9272 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9273 * to by the ·actual value·s of the ref [attribute] of the
9274 * <attributeGroup> [children], if any."
9275 */
9276 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9277 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9278 lastUse) == -1) {
9279 return (-1);
9280 }
9281 } else {
9282 /* W3C: "1 The set of attribute uses corresponding to the
9283 * <attribute> [children], if any."
9284 */
9285 tmp = (xmlSchemaAttributeLinkPtr)
9286 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9287 if (tmp == NULL) {
9288 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9289 return (-1);
9290 }
9291 tmp->attr = cur;
9292 tmp->next = NULL;
9293 if (*uses == NULL)
9294 *uses = tmp;
9295 else
9296 (*lastUse)->next = tmp;
9297 *lastUse = tmp;
9298 }
9299 cur = cur->next;
9300 }
9301 return (0);
9302}
9303
Daniel Veillard50355f02004-06-08 17:52:16 +00009304/**
9305 * xmlSchemaCloneWildcardNsConstraints:
9306 * @ctxt: the schema parser context
9307 * @dest: the destination wildcard
9308 * @source: the source wildcard
9309 *
9310 * Clones the namespace constraints of source
9311 * and assignes them to dest.
9312 * Returns -1 on internal error, 0 otherwise.
9313 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009314static int
9315xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9316 xmlSchemaWildcardPtr *dest,
9317 xmlSchemaWildcardPtr source)
9318{
9319 xmlSchemaWildcardNsPtr cur, tmp, last;
9320
9321 if ((source == NULL) || (*dest == NULL))
9322 return(-1);
9323 (*dest)->any = source->any;
9324 cur = source->nsSet;
9325 last = NULL;
9326 while (cur != NULL) {
9327 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9328 if (tmp == NULL)
9329 return(-1);
9330 tmp->value = cur->value;
9331 if (last == NULL)
9332 (*dest)->nsSet = tmp;
9333 else
9334 last->next = tmp;
9335 last = tmp;
9336 cur = cur->next;
9337 }
9338 if ((*dest)->negNsSet != NULL)
9339 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9340 if (source->negNsSet != NULL) {
9341 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9342 if ((*dest)->negNsSet == NULL)
9343 return(-1);
9344 (*dest)->negNsSet->value = source->negNsSet->value;
9345 } else
9346 (*dest)->negNsSet = NULL;
9347 return(0);
9348}
9349
Daniel Veillard50355f02004-06-08 17:52:16 +00009350/**
9351 * xmlSchemaUnionWildcards:
9352 * @ctxt: the schema parser context
9353 * @completeWild: the first wildcard
9354 * @curWild: the second wildcard
9355 *
9356 * Unions the namespace constraints of the given wildcards.
9357 * @completeWild will hold the resulting union.
9358 * Returns a positive error code on failure, -1 in case of an
9359 * internal error, 0 otherwise.
9360 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009361static int
9362xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9363 xmlSchemaWildcardPtr completeWild,
9364 xmlSchemaWildcardPtr curWild)
9365{
9366 xmlSchemaWildcardNsPtr cur, curB, tmp;
9367
9368 /*
9369 * 1 If O1 and O2 are the same value, then that value must be the
9370 * value.
9371 */
9372 if ((completeWild->any == curWild->any) &&
9373 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9374 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9375
9376 if ((completeWild->negNsSet == NULL) ||
9377 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9378
9379 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009380 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009381
9382 /*
9383 * Check equality of sets.
9384 */
9385 cur = completeWild->nsSet;
9386 while (cur != NULL) {
9387 found = 0;
9388 curB = curWild->nsSet;
9389 while (curB != NULL) {
9390 if (cur->value == curB->value) {
9391 found = 1;
9392 break;
9393 }
9394 curB = curB->next;
9395 }
9396 if (!found)
9397 break;
9398 cur = cur->next;
9399 }
9400 if (found)
9401 return(0);
9402 } else
9403 return(0);
9404 }
9405 }
9406 /*
9407 * 2 If either O1 or O2 is any, then any must be the value
9408 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009409 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009410 if (completeWild->any == 0) {
9411 completeWild->any = 1;
9412 if (completeWild->nsSet != NULL) {
9413 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9414 completeWild->nsSet = NULL;
9415 }
9416 if (completeWild->negNsSet != NULL) {
9417 xmlFree(completeWild->negNsSet);
9418 completeWild->negNsSet = NULL;
9419 }
9420 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009421 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009422 }
9423 /*
9424 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9425 * then the union of those sets must be the value.
9426 */
9427 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9428 int found;
9429 xmlSchemaWildcardNsPtr start;
9430
9431 cur = curWild->nsSet;
9432 start = completeWild->nsSet;
9433 while (cur != NULL) {
9434 found = 0;
9435 curB = start;
9436 while (curB != NULL) {
9437 if (cur->value == curB->value) {
9438 found = 1;
9439 break;
9440 }
9441 curB = curB->next;
9442 }
9443 if (!found) {
9444 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9445 if (tmp == NULL)
9446 return (-1);
9447 tmp->value = cur->value;
9448 tmp->next = completeWild->nsSet;
9449 completeWild->nsSet = tmp;
9450 }
9451 cur = cur->next;
9452 }
9453
9454 return(0);
9455 }
9456 /*
9457 * 4 If the two are negations of different values (namespace names
9458 * or ·absent·), then a pair of not and ·absent· must be the value.
9459 */
9460 if ((completeWild->negNsSet != NULL) &&
9461 (curWild->negNsSet != NULL) &&
9462 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9463 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009464
9465 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009466 }
9467 /*
9468 * 5.
9469 */
9470 if (((completeWild->negNsSet != NULL) &&
9471 (completeWild->negNsSet->value != NULL) &&
9472 (curWild->nsSet != NULL)) ||
9473 ((curWild->negNsSet != NULL) &&
9474 (curWild->negNsSet->value != NULL) &&
9475 (completeWild->nsSet != NULL))) {
9476
9477 int nsFound, absentFound = 0;
9478
9479 if (completeWild->nsSet != NULL) {
9480 cur = completeWild->nsSet;
9481 curB = curWild->negNsSet;
9482 } else {
9483 cur = curWild->nsSet;
9484 curB = completeWild->negNsSet;
9485 }
9486 nsFound = 0;
9487 while (cur != NULL) {
9488 if (cur->value == NULL)
9489 absentFound = 1;
9490 else if (cur->value == curB->value)
9491 nsFound = 1;
9492 if (nsFound && absentFound)
9493 break;
9494 cur = cur->next;
9495 }
9496
9497 if (nsFound && absentFound) {
9498 /*
9499 * 5.1 If the set S includes both the negated namespace
9500 * name and ·absent·, then any must be the value.
9501 */
9502 completeWild->any = 1;
9503 if (completeWild->nsSet != NULL) {
9504 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9505 completeWild->nsSet = NULL;
9506 }
9507 if (completeWild->negNsSet != NULL) {
9508 xmlFree(completeWild->negNsSet);
9509 completeWild->negNsSet = NULL;
9510 }
9511 } else if (nsFound && (!absentFound)) {
9512 /*
9513 * 5.2 If the set S includes the negated namespace name
9514 * but not ·absent·, then a pair of not and ·absent· must
9515 * be the value.
9516 */
9517 if (completeWild->nsSet != NULL) {
9518 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9519 completeWild->nsSet = NULL;
9520 }
9521 if (completeWild->negNsSet == NULL) {
9522 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9523 if (completeWild->negNsSet == NULL)
9524 return (-1);
9525 }
9526 completeWild->negNsSet->value = NULL;
9527 } else if ((!nsFound) && absentFound) {
9528 /*
9529 * 5.3 If the set S includes ·absent· but not the negated
9530 * namespace name, then the union is not expressible.
9531 */
9532 xmlSchemaPErr(ctxt, completeWild->node,
9533 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009534 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009535 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009536 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009537 } else if ((!nsFound) && (!absentFound)) {
9538 /*
9539 * 5.4 If the set S does not include either the negated namespace
9540 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9541 * and a namespace name must be the value.
9542 */
9543 if (completeWild->negNsSet == NULL) {
9544 if (completeWild->nsSet != NULL) {
9545 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9546 completeWild->nsSet = NULL;
9547 }
9548 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9549 if (completeWild->negNsSet == NULL)
9550 return (-1);
9551 completeWild->negNsSet->value = curWild->negNsSet->value;
9552 }
9553 }
9554 return (0);
9555 }
9556 /*
9557 * 6.
9558 */
9559 if (((completeWild->negNsSet != NULL) &&
9560 (completeWild->negNsSet->value == NULL) &&
9561 (curWild->nsSet != NULL)) ||
9562 ((curWild->negNsSet != NULL) &&
9563 (curWild->negNsSet->value == NULL) &&
9564 (completeWild->nsSet != NULL))) {
9565
9566 if (completeWild->nsSet != NULL) {
9567 cur = completeWild->nsSet;
9568 } else {
9569 cur = curWild->nsSet;
9570 }
9571 while (cur != NULL) {
9572 if (cur->value == NULL) {
9573 /*
9574 * 6.1 If the set S includes ·absent·, then any must be the
9575 * value.
9576 */
9577 completeWild->any = 1;
9578 if (completeWild->nsSet != NULL) {
9579 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9580 completeWild->nsSet = NULL;
9581 }
9582 if (completeWild->negNsSet != NULL) {
9583 xmlFree(completeWild->negNsSet);
9584 completeWild->negNsSet = NULL;
9585 }
9586 return (0);
9587 }
9588 cur = cur->next;
9589 }
9590 if (completeWild->negNsSet == NULL) {
9591 /*
9592 * 6.2 If the set S does not include ·absent·, then a pair of not
9593 * and ·absent· must be the value.
9594 */
9595 if (completeWild->nsSet != NULL) {
9596 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9597 completeWild->nsSet = NULL;
9598 }
9599 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9600 if (completeWild->negNsSet == NULL)
9601 return (-1);
9602 completeWild->negNsSet->value = NULL;
9603 }
9604 return (0);
9605 }
9606 return (0);
9607
9608}
9609
Daniel Veillard50355f02004-06-08 17:52:16 +00009610/**
9611 * xmlSchemaIntersectWildcards:
9612 * @ctxt: the schema parser context
9613 * @completeWild: the first wildcard
9614 * @curWild: the second wildcard
9615 *
9616 * Intersects the namespace constraints of the given wildcards.
9617 * @completeWild will hold the resulting intersection.
9618 * Returns a positive error code on failure, -1 in case of an
9619 * internal error, 0 otherwise.
9620 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009621static int
9622xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9623 xmlSchemaWildcardPtr completeWild,
9624 xmlSchemaWildcardPtr curWild)
9625{
William M. Brack803812b2004-06-03 02:11:24 +00009626 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009627
9628 /*
9629 * 1 If O1 and O2 are the same value, then that value must be the
9630 * value.
9631 */
9632 if ((completeWild->any == curWild->any) &&
9633 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9634 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9635
9636 if ((completeWild->negNsSet == NULL) ||
9637 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9638
9639 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009640 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009641
9642 /*
9643 * Check equality of sets.
9644 */
9645 cur = completeWild->nsSet;
9646 while (cur != NULL) {
9647 found = 0;
9648 curB = curWild->nsSet;
9649 while (curB != NULL) {
9650 if (cur->value == curB->value) {
9651 found = 1;
9652 break;
9653 }
9654 curB = curB->next;
9655 }
9656 if (!found)
9657 break;
9658 cur = cur->next;
9659 }
9660 if (found)
9661 return(0);
9662 } else
9663 return(0);
9664 }
9665 }
9666 /*
9667 * 2 If either O1 or O2 is any, then the other must be the value.
9668 */
9669 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9670 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9671 return(-1);
9672 return(0);
9673 }
9674 /*
9675 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9676 * name or ·absent·) and the other is a set of (namespace names or
9677 * ·absent·), then that set, minus the negated value if it was in
9678 * the set, minus ·absent· if it was in the set, must be the value.
9679 */
9680 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9681 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9682 const xmlChar *neg;
9683
9684 if (completeWild->nsSet == NULL) {
9685 neg = completeWild->negNsSet->value;
9686 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9687 return(-1);
9688 } else
9689 neg = curWild->negNsSet->value;
9690 /*
9691 * Remove absent and negated.
9692 */
9693 prev = NULL;
9694 cur = completeWild->nsSet;
9695 while (cur != NULL) {
9696 if (cur->value == NULL) {
9697 if (prev == NULL)
9698 completeWild->nsSet = cur->next;
9699 else
9700 prev->next = cur->next;
9701 xmlFree(cur);
9702 break;
9703 }
9704 prev = cur;
9705 cur = cur->next;
9706 }
9707 if (neg != NULL) {
9708 prev = NULL;
9709 cur = completeWild->nsSet;
9710 while (cur != NULL) {
9711 if (cur->value == neg) {
9712 if (prev == NULL)
9713 completeWild->nsSet = cur->next;
9714 else
9715 prev->next = cur->next;
9716 xmlFree(cur);
9717 break;
9718 }
9719 prev = cur;
9720 cur = cur->next;
9721 }
9722 }
9723
9724 return(0);
9725 }
9726 /*
9727 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9728 * then the intersection of those sets must be the value.
9729 */
9730 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9731 int found;
9732
9733 cur = completeWild->nsSet;
9734 prev = NULL;
9735 while (cur != NULL) {
9736 found = 0;
9737 curB = curWild->nsSet;
9738 while (curB != NULL) {
9739 if (cur->value == curB->value) {
9740 found = 1;
9741 break;
9742 }
9743 curB = curB->next;
9744 }
9745 if (!found) {
9746 if (prev == NULL)
9747 completeWild->nsSet = cur->next;
9748 else
9749 prev->next = cur->next;
9750 tmp = cur->next;
9751 xmlFree(cur);
9752 cur = tmp;
9753 continue;
9754 }
9755 prev = cur;
9756 cur = cur->next;
9757 }
9758
9759 return(0);
9760 }
9761 /* 5 If the two are negations of different namespace names,
9762 * then the intersection is not expressible
9763 */
9764 if ((completeWild->negNsSet != NULL) &&
9765 (curWild->negNsSet != NULL) &&
9766 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9767 (completeWild->negNsSet->value != NULL) &&
9768 (curWild->negNsSet->value != NULL)) {
9769
9770 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009771 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009772 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009773 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009774 }
9775 /*
9776 * 6 If the one is a negation of a namespace name and the other
9777 * is a negation of ·absent·, then the one which is the negation
9778 * of a namespace name must be the value.
9779 */
9780 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9781 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9782 (completeWild->negNsSet->value == NULL)) {
9783 completeWild->negNsSet->value = curWild->negNsSet->value;
9784 }
9785 return(0);
9786}
9787
Daniel Veillard50355f02004-06-08 17:52:16 +00009788/**
9789 * xmlSchemaIsWildcardNsConstraintSubset:
9790 * @ctxt: the schema parser context
9791 * @wildA: the first wildcard
9792 * @wildB: the second wildcard
9793 *
9794 * Returns 1 if the namespace constraint of @wildA is an intensional
9795 * subset of @wildB, 0 otherwise.
9796 */
9797static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009798xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9799 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009800{
Daniel Veillard3646d642004-06-02 19:19:14 +00009801
Daniel Veillard50355f02004-06-08 17:52:16 +00009802 /*
9803 * Schema Component Constraint: Wildcard Subset
9804 */
9805 /*
9806 * 1 super must be any.
9807 */
9808 if (wildB->any)
9809 return (1);
9810 /*
9811 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9812 * 2.2 super must be a pair of not and the same value.
9813 */
9814 if ((wildA->negNsSet != NULL) &&
9815 (wildB->negNsSet != NULL) &&
9816 (wildA->negNsSet->value == wildA->negNsSet->value))
9817 return (1);
9818 /*
9819 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9820 */
9821 if (wildA->nsSet != NULL) {
9822 /*
9823 * 3.2.1 super must be the same set or a superset thereof.
9824 */
9825 if (wildB->nsSet != NULL) {
9826 xmlSchemaWildcardNsPtr cur, curB;
9827 int found = 0;
9828
9829 cur = wildA->nsSet;
9830 while (cur != NULL) {
9831 found = 0;
9832 curB = wildB->nsSet;
9833 while (curB != NULL) {
9834 if (cur->value == curB->value) {
9835 found = 1;
9836 break;
9837 }
9838 curB = curB->next;
9839 }
9840 if (!found)
9841 return (0);
9842 cur = cur->next;
9843 }
9844 if (found)
9845 return (1);
9846 } else if (wildB->negNsSet != NULL) {
9847 xmlSchemaWildcardNsPtr cur;
9848 /*
9849 * 3.2.2 super must be a pair of not and a namespace name or
9850 * ·absent· and that value must not be in sub's set.
9851 */
9852 cur = wildA->nsSet;
9853 while (cur != NULL) {
9854 if (cur->value == wildB->negNsSet->value)
9855 return (0);
9856 cur = cur->next;
9857 }
9858 return (1);
9859 }
9860 }
9861 return (0);
9862}
9863
9864/**
9865 * xmlSchemaBuildCompleteAttributeWildcard:
9866 * @ctxt: the schema parser context
9867 * @attrs: the attribute list
9868 * @completeWild: the resulting complete wildcard
9869 *
9870 * Returns -1 in case of an internal error, 0 otherwise.
9871 */
9872static int
9873xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9874 xmlSchemaAttributePtr attrs,
9875 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009876{
9877 while (attrs != NULL) {
9878 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9879 xmlSchemaAttributeGroupPtr group;
9880
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009881 group = (xmlSchemaAttributeGroupPtr) attrs;
9882 /*
9883 * Handle attribute group references.
9884 */
9885 if (group->ref != NULL) {
9886 if (group->refItem == NULL) {
9887 /*
9888 * TODO: Should we raise a warning here?
9889 */
9890 /*
9891 * The referenced attribute group definition could not
9892 * be resolved beforehand, so skip.
9893 */
9894 attrs = attrs->next;
9895 continue;
9896 } else
9897 group = group->refItem;
9898 }
9899 /*
9900 * For every attribute group definition, an intersected wildcard
9901 * will be created (assumed that a wildcard exists on the
9902 * particular attr. gr. def. or on any contained attr. gr. def
9903 * at all).
9904 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
9905 * that the intersection will be performed only once.
9906 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009907 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9908 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009909 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9910 group->attributes, &group->attributeWildcard) == -1)
9911 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009912 }
9913 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9914 }
9915 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009916 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009917 /*
9918 * Copy the first encountered wildcard as context, except for the annotation.
9919 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009920 *completeWild = xmlSchemaAddWildcard(ctxt);
9921 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9922 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9923 completeWild, group->attributeWildcard) == -1)
9924 return (-1);
9925 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009926 /*
9927 * Although the complete wildcard might not correspond to any
9928 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009929 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +00009930 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009931 (*completeWild)->node = group->attributeWildcard->node;
9932
9933 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9934 xmlSchemaFreeWildcard(*completeWild);
9935 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009936 }
9937 }
9938 }
9939 attrs = attrs->next;
9940 }
9941
Daniel Veillard50355f02004-06-08 17:52:16 +00009942 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009943}
9944
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009945static int
9946xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
9947 int *fixed,
9948 const xmlChar **value,
9949 xmlSchemaValPtr *val)
9950{
9951 *fixed = 0;
9952 *value = NULL;
9953 if (val != 0)
9954 *val = NULL;
9955
9956 if (item->defValue == NULL)
9957 item = item->refDecl;
9958
9959 if (item == NULL)
9960 return (0);
9961
9962 if (item->defValue != NULL) {
9963 *value = item->defValue;
9964 if (val != 0)
9965 *val = item->defVal;
9966 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
9967 *fixed = 1;
9968 return (1);
9969 }
9970 return (0);
9971}
Daniel Veillard3646d642004-06-02 19:19:14 +00009972/**
9973 * xmlSchemaMatchesWildcardNs:
9974 * @wild: the wildcard
9975 * @ns: the namespace
9976 *
9977 *
9978 * Returns 1 if the given namespace matches the wildcard,
9979 * 0 otherwise.
9980 */
9981static int
9982xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
9983{
9984 if (wild == NULL)
9985 return(0);
9986
9987 if (wild->any)
9988 return(1);
9989 else if (wild->nsSet != NULL) {
9990 xmlSchemaWildcardNsPtr cur;
9991
9992 cur = wild->nsSet;
9993 while (cur != NULL) {
9994 if (xmlStrEqual(cur->value, ns))
9995 return(1);
9996 cur = cur->next;
9997 }
9998 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
9999 (!xmlStrEqual(wild->negNsSet->value, ns)))
10000 return(1);
10001
10002 return(0);
10003}
10004
10005/**
10006 * xmlSchemaBuildAttributeValidation:
10007 * @ctxt: the schema parser context
10008 * @type: the complex type definition
10009 *
10010 *
10011 * Builds the wildcard and the attribute uses on the given complex type.
10012 * Returns -1 if an internal error occurs, 0 otherwise.
10013 */
10014static int
10015xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10016{
10017 xmlSchemaTypePtr baseType = NULL;
10018 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010019 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010020 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010021 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010022 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010023 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010024 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010025
Daniel Veillard01fa6152004-06-29 17:04:39 +000010026 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010027 /*
10028 * Complex Type Definition with complex content Schema Component.
10029 *
10030 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010031 * TODO: Add checks for absent referenced attribute declarations and
10032 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010033 */
10034 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010035 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010036 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010037 "attribute uses already builded.\n",
10038 NULL, NULL);
10039 return (-1);
10040 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010041 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010042 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010043 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010044 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010045 type->name, NULL);
10046 return (-1);
10047 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010048 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010049 if (baseType == anyType)
10050 baseIsAnyType = 1;
10051 /*
10052 * Inherit the attribute uses of the base type.
10053 */
10054 /*
10055 * NOTE: It is allowed to "extend" the anyType complex type.
10056 */
10057 if (!baseIsAnyType) {
10058 if (baseType != NULL) {
10059 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10060 tmp = (xmlSchemaAttributeLinkPtr)
10061 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10062 if (tmp == NULL) {
10063 xmlSchemaPErrMemory(ctxt,
10064 "building attribute uses of complexType", NULL);
10065 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010066 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010067 tmp->attr = cur->attr;
10068 tmp->next = NULL;
10069 if (type->attributeUses == NULL) {
10070 type->attributeUses = tmp;
10071 } else
10072 lastBaseUse->next = tmp;
10073 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010074 }
10075 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010076 }
10077 if ((type->subtypes != NULL) &&
10078 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10079 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010080 /*
10081 * type --> (<simpleContent>|<complexContent>)
10082 * --> (<restriction>|<extension>) --> attributes
10083 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010084 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010085 } else {
10086 /* Short hand form of the complexType. */
10087 attrs = type->attributes;
10088 }
10089 /*
10090 * Handle attribute wildcards.
10091 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010092 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10093 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010094 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010095 * NOTE: During the parse time, the wildcard is created on the complexType
10096 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010097 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010098 if (err == -1) {
10099 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10100 "Internal error: xmlSchemaBuildAttributeValidation: "
10101 "failed to build an intersected attribute wildcard.\n",
10102 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010103 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010104 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010105
10106 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10107 ((baseIsAnyType) ||
10108 ((baseType != NULL) &&
10109 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10110 (baseType->attributeWildcard != NULL)))) {
10111 if (type->attributeWildcard != NULL) {
10112 /*
10113 * Union the complete wildcard with the base wildcard.
10114 */
10115 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10116 baseType->attributeWildcard) == -1)
10117 return (-1);
10118 } else {
10119 /*
10120 * Just inherit the wildcard.
10121 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010122 /*
10123 * NOTE: This is the only case where an attribute
10124 * wildcard is shared.
10125 */
10126 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10127 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010128 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010129 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010130 }
10131
10132 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10133 if (type->attributeWildcard != NULL) {
10134 /*
10135 * Derivation Valid (Restriction, Complex)
10136 * 4.1 The {base type definition} must also have one.
10137 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010138 if (baseType->attributeWildcard == NULL) {
10139 xmlSchemaPCustomErr(ctxt,
10140 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10141 NULL, type, NULL,
10142 "The type has an attribute wildcard, "
10143 "but the base type %s does not have one",
10144 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10145 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010146 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010147 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010148 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10149 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010150 xmlSchemaPCustomErr(ctxt,
10151 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10152 NULL, type, NULL,
10153 "The attribute wildcard is not a valid "
10154 "subset of the wildcard in the base type %s",
10155 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10156 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010157 return (1);
10158 }
10159 /* 4.3 Unless the {base type definition} is the ·ur-type
10160 * definition·, the complex type definition's {attribute
10161 * wildcard}'s {process contents} must be identical to or
10162 * stronger than the {base type definition}'s {attribute
10163 * wildcard}'s {process contents}, where strict is stronger
10164 * than lax is stronger than skip.
10165 */
10166 if ((type->baseType != anyType) &&
10167 (type->attributeWildcard->processContents <
10168 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010169 xmlSchemaPCustomErr(ctxt,
10170 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10171 NULL, type, NULL,
10172 "The 'process contents' of the attribute wildcard is weaker than "
10173 "the one in the base type %s",
10174 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10175 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010176 return (1);
10177 }
10178 }
10179 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10180 /*
10181 * Derivation Valid (Extension)
10182 * At this point the type and the base have both, either
10183 * no wildcard or a wildcard.
10184 */
10185 if ((baseType->attributeWildcard != NULL) &&
10186 (baseType->attributeWildcard != type->attributeWildcard)) {
10187 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010188 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010189 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010190 xmlSchemaPCustomErr(ctxt,
10191 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10192 NULL, type, NULL,
10193 "The attribute wildcard is not a valid "
10194 "superset of the one in the base type %s",
10195 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10196 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010197 return (1);
10198 }
10199 }
10200 }
10201
Daniel Veillard3646d642004-06-02 19:19:14 +000010202 /*
10203 * Gather attribute uses defined by this type.
10204 */
10205 if (attrs != NULL) {
10206 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10207 &uses, &lastUse) == -1) {
10208 return (-1);
10209 }
10210 }
10211 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10212 * "Two distinct attribute declarations in the {attribute uses} must
10213 * not have identical {name}s and {target namespace}s."
10214 *
10215 * For "extension" this is done further down.
10216 */
10217 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10218 cur = uses;
10219 while (cur != NULL) {
10220 tmp = cur->next;
10221 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010222 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10223 xmlSchemaGetAttrName(tmp->attr))) &&
10224 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10225 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10226
10227 xmlSchemaPAttrUseErr(ctxt,
10228 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10229 NULL, type, NULL, cur->attr,
10230 "Duplicate attribute use %s specified",
10231 xmlSchemaFormatNsUriLocal(&str,
10232 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10233 xmlSchemaGetAttrName(tmp->attr))
10234 );
10235 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010236 break;
10237 }
10238 tmp = tmp->next;
10239 }
10240 cur = cur->next;
10241 }
10242 }
10243 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10244 /*
10245 * Derive by restriction.
10246 */
10247 if (baseIsAnyType) {
10248 type->attributeUses = uses;
10249 } else {
10250 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010251 const xmlChar *bEffValue;
10252 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010253
10254 cur = uses;
10255 while (cur != NULL) {
10256 found = 0;
10257 base = type->attributeUses;
10258 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010259 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10260 xmlSchemaGetAttrName(base->attr)) &&
10261 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10262 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010263
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010264 found = 1;
10265
Daniel Veillard3646d642004-06-02 19:19:14 +000010266 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10267 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10268 /*
10269 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010270 */
10271 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010272 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010273 NULL, type, NULL, cur->attr,
10274 "The 'optional' use is inconsistent with a matching "
10275 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010276 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10277 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10278 /*
10279 * derivation-ok-restriction 3
10280 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010281 xmlSchemaPCustomErr(ctxt,
10282 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10283 NULL, type, NULL,
10284 "A matching attribute use for the 'required' "
10285 "attribute use %s of the base type is missing",
10286 xmlSchemaFormatNsUriLocal(&str,
10287 xmlSchemaGetAttrTargetNsURI(base->attr),
10288 xmlSchemaGetAttrName(base->attr)));
10289 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010290 } else {
10291 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010292 * 2.1.3 [Definition:] Let the effective value
10293 * constraint of an attribute use be its {value
10294 * constraint}, if present, otherwise its {attribute
10295 * declaration}'s {value constraint} .
10296 */
10297 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10298 &bEffValue, 0);
10299 /*
10300 * 2.1.3 ... one of the following must be true
10301 *
10302 * 2.1.3.1 B's ·effective value constraint· is
10303 * ·absent· or default.
10304 */
10305 if ((bEffValue != NULL) &&
10306 (effFixed == 1)) {
10307 const xmlChar *rEffValue = NULL;
10308
10309 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10310 &rEffValue, 0);
10311 /*
10312 * 2.1.3.2 R's ·effective value constraint· is
10313 * fixed with the same string as B's.
10314 */
10315 if ((effFixed == 0) ||
10316 (! xmlStrEqual(rEffValue, bEffValue))) {
10317 xmlSchemaPAttrUseErr(ctxt,
10318 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10319 NULL, type, NULL, cur->attr,
10320 "The effective value constraint of the "
10321 "attribute use is inconsistent with "
10322 "its correspondent of the base type",
10323 NULL);
10324 }
10325 }
10326 /*
10327 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10328 */
10329 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010330 * Override the attribute use.
10331 */
10332 base->attr = cur->attr;
10333 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010334
Daniel Veillard3646d642004-06-02 19:19:14 +000010335 break;
10336 }
10337 base = base->next;
10338 }
10339
10340 if (!found) {
10341 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10342 /*
10343 * derivation-ok-restriction 2.2
10344 */
10345 if ((type->attributeWildcard != NULL) &&
10346 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10347 cur->attr->targetNamespace))
10348 found = 1;
10349
10350 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010351 xmlSchemaPAttrUseErr(ctxt,
10352 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10353 NULL, type, NULL, cur->attr,
10354 "Neither a matching attribute use, "
10355 "nor a matching wildcard in the base type does exist",
10356 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010357 } else {
10358 /*
10359 * Add the attribute use.
10360 *
10361 * Note that this may lead to funny derivation error reports, if
10362 * multiple equal attribute uses exist; but this is not
10363 * allowed anyway, and it will be reported beforehand.
10364 */
10365 tmp = cur;
10366 if (prev != NULL)
10367 prev->next = cur->next;
10368 else
10369 uses = cur->next;
10370 cur = cur->next;
10371 if (type->attributeUses == NULL) {
10372 type->attributeUses = tmp;
10373 } else
10374 lastBaseUse->next = tmp;
10375 lastBaseUse = tmp;
10376
10377 continue;
10378 }
10379 }
10380 }
10381 prev = cur;
10382 cur = cur->next;
10383 }
10384 if (uses != NULL)
10385 xmlSchemaFreeAttributeUseList(uses);
10386 }
10387 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10388 /*
10389 * The spec allows only appending, and not other kinds of extensions.
10390 *
10391 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10392 */
10393 if (uses != NULL) {
10394 if (type->attributeUses == NULL) {
10395 type->attributeUses = uses;
10396 } else
10397 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010398 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010399 } else {
10400 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010401 * Derive implicitely from the ur-type.
10402 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010403 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010404 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010405 /*
10406 * 3.4.6 -> Complex Type Definition Properties Correct
10407 */
10408 if (type->attributeUses != NULL) {
10409 cur = type->attributeUses;
10410 prev = NULL;
10411 while (cur != NULL) {
10412 /*
10413 * 4. Two distinct attribute declarations in the {attribute uses} must
10414 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010415 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010416 * Note that this was already done for "restriction" and types derived from
10417 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010418 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010419 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10420 tmp = cur->next;
10421 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010422 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10423 xmlSchemaGetAttrName(tmp->attr))) &&
10424 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10425 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010426
Daniel Veillardc0826a72004-08-10 14:17:33 +000010427 xmlSchemaPAttrUseErr(ctxt,
10428 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10429 NULL, type, NULL, tmp->attr,
10430 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010431 break;
10432 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010433 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010434 }
10435 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010436 /*
10437 * 5. Two distinct attribute declarations in the {attribute uses} must
10438 * not have {type definition}s which are or are derived from ID.
10439 */
10440 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010441 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010442 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010443 xmlSchemaPAttrUseErr(ctxt,
10444 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10445 NULL, type, NULL, cur->attr,
10446 "There must not exist more than one attribute use, "
10447 "declared of type 'ID' or derived from it",
10448 NULL);
10449 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010450 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010451 id = cur;
10452 }
10453 /*
10454 * Remove "prohibited" attribute uses. The reason this is done at this late
10455 * stage is to be able to catch dublicate attribute uses. So we had to keep
10456 * prohibited uses in the list as well.
10457 */
10458 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10459 tmp = cur;
10460 if (prev == NULL)
10461 type->attributeUses = cur->next;
10462 else
10463 prev->next = cur->next;
10464 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010465 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010466 } else {
10467 prev = cur;
10468 cur = cur->next;
10469 }
10470 }
10471 }
10472 /*
10473 * TODO: This check should be removed if we are 100% sure of
10474 * the base type attribute uses already being built.
10475 */
10476 if ((baseType != NULL) && (!baseIsAnyType) &&
10477 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10478 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010479 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010480 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010481 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010482 baseType->name, NULL);
10483 }
10484 return (0);
10485}
10486
10487/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010488 * xmlSchemaTypeFinalContains:
10489 * @schema: the schema
10490 * @type: the type definition
10491 * @final: the final
10492 *
10493 * Evaluates if a type definition contains the given "final".
10494 * This does take "finalDefault" into account as well.
10495 *
10496 * Returns 1 if the type does containt the given "final",
10497 * 0 otherwise.
10498 */
10499static int
10500xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10501{
10502 int tfinal = final, tflags = type->flags;
10503
10504 if (type == NULL)
10505 return (0);
10506 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10507 switch (final) {
10508 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10509 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10510 break;
10511 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10512 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10513 break;
10514 case XML_SCHEMAS_TYPE_FINAL_LIST:
10515 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10516 break;
10517 case XML_SCHEMAS_TYPE_FINAL_UNION:
10518 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10519 break;
10520 }
10521 tflags = schema->flags;
10522 }
10523 if (tflags & tfinal)
10524 return (1);
10525 else
10526 return (0);
10527
10528}
10529
10530/**
10531 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10532 * @type: the Union Simple Type
10533 *
10534 * Returns a list of member types of @type if existing,
10535 * returns NULL otherwise.
10536 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010537static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010538xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10539{
10540 while (type != NULL) {
10541 if (type->memberTypes != NULL)
10542 return (type->memberTypes);
10543 else
10544 type = type->baseType;
10545 }
10546 return (NULL);
10547}
10548
10549/**
10550 * xmlSchemaGetListSimpleTypeItemType:
10551 * @type: the simple type definition
10552 *
10553 * Returns the item type definition of the list simple type.
10554 */
10555static xmlSchemaTypePtr
10556xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10557{
10558 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10559 return (NULL);
10560 /*
10561 * Note: In libxml2, the built-in types do not reflect
10562 * the datatype hierarchy (yet?) - we have to treat them
10563 * in a special way.
10564 */
10565 if (type->type == XML_SCHEMA_TYPE_BASIC)
10566 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10567 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10568 /* 1 If the <list> alternative is chosen, then the type
10569 * definition ·resolved· to by the ·actual value· of the
10570 * itemType [attribute] of <list>, if present, otherwise
10571 * the type definition corresponding to the <simpleType>
10572 * among the [children] of <list>.
10573 */
10574 return (type->subtypes->subtypes);
10575 else {
10576 /* 2 If the <restriction> option is chosen, then the
10577 * {item type definition} of the {base type definition}.
10578 */
10579 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10580 }
10581}
10582
10583/**
10584 * xmlSchemaCheckCOSSTDerivedOK:
10585 * @type: the derived simple type definition
10586 * @baseType: the base type definition
10587 *
10588 * Checks wheter @type can be validly
10589 * derived from @baseType.
10590 *
10591 * Returns 0 on success, an positive error code otherwise.
10592 */
10593static int
10594xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10595 xmlSchemaTypePtr type,
10596 xmlSchemaTypePtr baseType,
10597 int subset)
10598{
10599 /*
10600 * Schema Component Constraint: Type Derivation OK (Simple)
10601 *
10602 *
10603 * 1 They are the same type definition.
10604 * TODO: The identy check might have to be more complex than this.
10605 */
10606 if (type == baseType)
10607 return (0);
10608 /*
10609 * 2.1 restriction is not in the subset, or in the {final}
10610 * of its own {base type definition};
10611 */
10612 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10613 (xmlSchemaTypeFinalContains(schema,
10614 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10615 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10616 }
10617 /* 2.2 */
10618 if (type->baseType == baseType) {
10619 /*
10620 * 2.2.1 D's ·base type definition· is B.
10621 */
10622 return (0);
10623 }
10624 /*
10625 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10626 * and is validly derived from B given the subset, as defined by this
10627 * constraint.
10628 */
10629 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10630 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10631 return (0);
10632 }
10633 /*
10634 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10635 * definition·.
10636 */
10637 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10638 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10639 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10640 return (0);
10641 }
10642 /*
10643 * 2.2.4 B's {variety} is union and D is validly derived from a type
10644 * definition in B's {member type definitions} given the subset, as
10645 * defined by this constraint.
10646 *
10647 * NOTE: This seems not to involve built-in types, since there is no
10648 * built-in Union Simple Type.
10649 */
10650 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10651 xmlSchemaTypeLinkPtr cur;
10652
10653 cur = baseType->memberTypes;
10654 while (cur != NULL) {
10655 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10656 cur->type, subset) == 0)
10657 return (0);
10658 cur = cur->next;
10659 }
10660 }
10661
10662 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10663}
10664
10665
10666/**
10667 * xmlSchemaCheckSTPropsCorrect:
10668 * @ctxt: the schema parser context
10669 * @type: the simple type definition
10670 *
10671 * Checks st-props-correct.
10672 *
10673 * Returns 0 if the properties are correct,
10674 * if not, a positive error code and -1 on internal
10675 * errors.
10676 */
10677static int
10678xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10679 xmlSchemaTypePtr type)
10680{
10681 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10682 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010683 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010684
Daniel Veillardc0826a72004-08-10 14:17:33 +000010685 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010686 /*
10687 * Schema Component Constraint: Simple Type Definition Properties Correct
10688 *
10689 * NOTE: This is somehow redundant, since we actually built a simple type
10690 * to have all the needed information; this acts as an self test.
10691 */
10692 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10693 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10694 /*
10695 * TODO: 1 The values of the properties of a simple type definition must be as
10696 * described in the property tableau in Datatype definition, modulo the
10697 * impact of Missing Sub-components (§5.3).
10698 */
10699 /* Base type: If the datatype has been ·derived· by ·restriction·
10700 * then the Simple Type Definition component from which it is ·derived·,
10701 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10702 */
10703 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010704 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010705 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010706 NULL, type, NULL,
10707 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010708 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10709 }
10710 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10711 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10712 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010713 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010714 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010715 NULL, type, NULL,
10716 "The base type %s is not a simple type",
10717 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10718 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010719 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10720 }
10721 if ((baseType != anySimpleType) &&
10722 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010723 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010724 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010725 NULL, type, NULL,
10726 "A type, derived by list or union, must have"
10727 "the simple ur-type definition as base type, not %s",
10728 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10729 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010730 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10731 }
10732 /*
10733 * Variety: One of {atomic, list, union}.
10734 */
10735 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10736 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10737 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010738 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010739 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010740 NULL, type, NULL,
10741 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010742 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10743 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010744 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010745
10746 /*
10747 * 2 All simple type definitions must be derived ultimately from the ·simple
10748 * ur-type definition (so· circular definitions are disallowed). That is, it
10749 * must be possible to reach a built-in primitive datatype or the ·simple
10750 * ur-type definition· by repeatedly following the {base type definition}.
10751 */
10752 baseType = type->baseType;
10753 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10754 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10755 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10756 if (baseType == anySimpleType)
10757 break;
10758 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010759 xmlSchemaPCustomErr(ctxt,
10760 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10761 NULL, type, NULL,
10762 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010763 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10764 }
10765 baseType = baseType->baseType;
10766 }
10767 /*
10768 * 3 The {final} of the {base type definition} must not contain restriction.
10769 */
10770 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10771 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010772 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010773 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010774 NULL, type, NULL,
10775 "The 'final' of its base type %s must not contain "
10776 "'restriction'",
10777 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10778 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010779 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10780 }
10781 return (0);
10782}
10783
10784/**
10785 * xmlSchemaCheckDerivationValidSimpleRestriction:
10786 * @ctxt: the schema parser context
10787 * @type: the simple type definition
10788 *
10789 * Checks if the given @type (simpleType) is derived
10790 * validly by restriction.
10791 *
10792 * Returns -1 on internal errors, 0 if the type is validly derived,
10793 * a positive error code otherwise.
10794 */
10795static int
10796xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010797 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010798{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010799 xmlChar *str = NULL;
10800
10801 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010802
10803 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10804 xmlSchemaPErr(ctxt, type->node,
10805 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010806 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10807 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010808 type->name, NULL);
10809 return (-1);
10810 }
10811
10812 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10813 xmlSchemaTypePtr primitive;
10814 /*
10815 * 1.1 The {base type definition} must be an atomic simple
10816 * type definition or a built-in primitive datatype.
10817 */
10818 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010819 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010820 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010821 NULL, type, NULL,
10822 "The base type %s is not an atomic simple type",
10823 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10824 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010825 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10826 }
10827 /* 1.2 The {final} of the {base type definition} must not contain
10828 * restriction.
10829 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010830 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010831 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10832 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010833 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010834 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010835 NULL, type, NULL,
10836 "The final of its base type %s must not contain 'restriction'",
10837 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10838 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010839 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10840 }
10841
10842 /*
10843 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10844 * type definition}, as specified in the appropriate subsection of 3.2
10845 * Primitive datatypes.
10846 */
10847 if (type->facets != NULL) {
10848 xmlSchemaFacetPtr facet;
10849 int ok = 1;
10850
10851 primitive = xmlSchemaGetPrimitiveType(type);
10852 if (primitive == NULL) {
10853 xmlSchemaPErr(ctxt, type->node,
10854 XML_ERR_INTERNAL_ERROR,
10855 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010856 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010857 type->name, NULL);
10858 return (-1);
10859 }
10860 facet = type->facets;
10861 do {
10862 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010863 ok = 0;
10864 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010865 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010866 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010867 }
10868 facet = facet->next;
10869 } while (facet != NULL);
10870 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010871 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010872 }
10873 /*
10874 * TODO: 1.3.2 (facet derivation)
10875 */
10876 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10877 xmlSchemaTypePtr itemType = NULL;
10878
10879 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10880 if (itemType == NULL) {
10881 xmlSchemaPErr(ctxt, type->node,
10882 XML_ERR_INTERNAL_ERROR,
10883 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010884 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010885 type->name, NULL);
10886 return (-1);
10887 }
10888 /*
10889 * 2.1 The {item type definition} must have a {variety} of atomic or
10890 * union (in which case all the {member type definitions}
10891 * must be atomic).
10892 */
10893 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10894 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010895 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010896 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010897 NULL, type, NULL,
10898 "The item type %s must have a variety of atomic or union",
10899 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10900 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010901 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10902 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10903 xmlSchemaTypeLinkPtr member;
10904
10905 member = itemType->memberTypes;
10906 while (member != NULL) {
10907 if ((member->type->flags &
10908 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010909 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010910 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010911 NULL, type, NULL,
10912 "The item type is a union type, but the "
10913 "member type %s of this item type is not atomic",
10914 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10915 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010916 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10917 }
10918 member = member->next;
10919 }
10920 }
10921
10922 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10923 xmlSchemaFacetPtr facet;
10924 /*
10925 * This is the case if we have: <simpleType><list ..
10926 */
10927 /*
10928 * 2.3.1
10929 * 2.3.1.1 The {final} of the {item type definition} must not
10930 * contain list.
10931 */
10932 if (xmlSchemaTypeFinalContains(ctxt->schema,
10933 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010934 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010935 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010936 NULL, type, NULL,
10937 "The final of its item type %s must not contain 'list'",
10938 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10939 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010940 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10941 }
10942 /*
10943 * 2.3.1.2 The {facets} must only contain the whiteSpace
10944 * facet component.
10945 */
10946 if (type->facets != NULL) {
10947 facet = type->facets;
10948 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010949 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10950 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010951 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010952 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010953 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10954 }
10955 facet = facet->next;
10956 } while (facet != NULL);
10957 }
10958 /*
10959 * TODO: Datatypes states:
10960 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10961 * whose ·lexical space· allows space (such as string or anyURI)or
10962 * a ·union· datatype any of whose {member type definitions}'s
10963 * ·lexical space· allows space.
10964 */
10965 } else {
10966 /*
10967 * This is the case if we have: <simpleType><restriction ...
10968 */
10969 /*
10970 * 2.3.2
10971 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10972 */
10973 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010974 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010975 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010976 NULL, type, NULL,
10977 "The base type %s must be a list type",
10978 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10979 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010980 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
10981 }
10982 /*
10983 * 2.3.2.2 The {final} of the {base type definition} must not
10984 * contain restriction.
10985 */
10986 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10987 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010988 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010989 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010990 NULL, type, NULL,
10991 "The final of the base type %s must not contain 'restriction'",
10992 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10993 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010994 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
10995 }
10996 /*
10997 * 2.3.2.3 The {item type definition} must be validly derived
10998 * from the {base type definition}'s {item type definition} given
10999 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11000 */
11001 {
11002 xmlSchemaTypePtr baseItemType;
11003
11004 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11005 if (baseItemType == NULL) {
11006 xmlSchemaPErr(ctxt, type->node,
11007 XML_ERR_INTERNAL_ERROR,
11008 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011009 "List simple type '%s': Failed to "
11010 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011011 type->name, type->baseType->name);
11012 return (-1);
11013 }
11014 if ((itemType != baseItemType) &&
11015 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11016 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011017 xmlChar *strBIT = NULL, *strBT = NULL;
11018 xmlSchemaPCustomErrExt(ctxt,
11019 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11020 NULL, type, NULL,
11021 "The item type %s is not validly derived from the "
11022 "item type %s of the base type %s",
11023 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11024 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11025 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11026
11027 FREE_AND_NULL(str)
11028 FREE_AND_NULL(strBIT)
11029 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011030 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11031 }
11032 }
11033
11034 if (type->facets != NULL) {
11035 xmlSchemaFacetPtr facet;
11036 int ok = 1;
11037 /*
11038 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11039 * and enumeration facet components are allowed among the {facets}.
11040 */
11041 facet = type->facets;
11042 do {
11043 switch (facet->type) {
11044 case XML_SCHEMA_FACET_LENGTH:
11045 case XML_SCHEMA_FACET_MINLENGTH:
11046 case XML_SCHEMA_FACET_MAXLENGTH:
11047 case XML_SCHEMA_FACET_WHITESPACE:
11048 /*
11049 * TODO: 2.5.1.2 List datatypes
11050 * The value of ·whiteSpace· is fixed to the value collapse.
11051 */
11052 case XML_SCHEMA_FACET_PATTERN:
11053 case XML_SCHEMA_FACET_ENUMERATION:
11054 break;
11055 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011056 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011057 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011058 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011059 /*
11060 * We could return, but it's nicer to report all
11061 * invalid facets.
11062 */
11063 ok = 0;
11064 }
11065 }
11066 facet = facet->next;
11067 } while (facet != NULL);
11068 if (ok == 0)
11069 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11070 /*
11071 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11072 * is a facet of the same kind in the {facets} of the {base type
11073 * definition} (call this BF),then the DF's {value} must be a valid
11074 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11075 */
11076 }
11077
11078
11079 }
11080 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11081 /*
11082 * 3.1 The {member type definitions} must all have {variety} of
11083 * atomic or list.
11084 */
11085 xmlSchemaTypeLinkPtr member;
11086
11087 member = type->memberTypes;
11088 while (member != NULL) {
11089 if (((member->type->flags &
11090 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11091 ((member->type->flags &
11092 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011093 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011094 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011095 NULL, type, NULL,
11096 "The member type %s is neither an atomic, nor a list type",
11097 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11098 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011099 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11100 }
11101 member = member->next;
11102 }
11103 /*
11104 * 3.3.1 If the {base type definition} is the ·simple ur-type
11105 * definition·
11106 */
11107 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11108 /*
11109 * 3.3.1.1 All of the {member type definitions} must have a
11110 * {final} which does not contain union.
11111 */
11112 member = type->memberTypes;
11113 while (member != NULL) {
11114 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11115 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011117 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011118 NULL, type, NULL,
11119 "The final of member type %s contains 'union'",
11120 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11121 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011122 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11123 }
11124 member = member->next;
11125 }
11126 /*
11127 * 3.3.1.2 The {facets} must be empty.
11128 */
11129 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011130 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011131 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011132 NULL, type, NULL,
11133 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011134 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11135 }
11136 } else {
11137 /*
11138 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11139 */
11140 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011141 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011142 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011143 NULL, type, NULL,
11144 "The base type %s is not a union type",
11145 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11146 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011147 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11148 }
11149 /*
11150 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11151 */
11152 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11153 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011154 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011155 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011156 NULL, type, NULL,
11157 "The final of its base type %s must not contain 'restriction'",
11158 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11159 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011160 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11161 }
11162 /*
11163 * 3.3.2.3 The {member type definitions}, in order, must be validly
11164 * derived from the corresponding type definitions in the {base
11165 * type definition}'s {member type definitions} given the empty set,
11166 * as defined in Type Derivation OK (Simple) (§3.14.6).
11167 */
11168 {
11169 xmlSchemaTypeLinkPtr baseMember;
11170
11171 /*
11172 * OPTIMIZE: if the type is restricting, it has no local defined
11173 * member types and inherits the member types of the base type;
11174 * thus a check for equality can be skipped.
11175 */
11176 /*
11177 * TODO: Even worse: I cannot see a scenario where a restricting
11178 * union simple type can have other member types as the member
11179 * types of it's base type. This check seems not necessary with
11180 * respect to the derivation process in libxml2.
11181 */
11182 if (type->memberTypes != NULL) {
11183 member = type->memberTypes;
11184 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11185 if ((member == NULL) && (baseMember != NULL)) {
11186 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011187 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011188 "Internal error: "
11189 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011190 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011191 "of member types in the base type\n",
11192 type->name, NULL);
11193 }
11194 while (member != NULL) {
11195 if (baseMember == NULL) {
11196 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011197 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011198 "Internal error: "
11199 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011200 "(3.3.2.3), union simple type '%s', unequal number "
11201 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011202 type->name, NULL);
11203 }
11204 if ((member->type != baseMember->type) &&
11205 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11206 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011207 xmlChar *strBMT = NULL, *strBT = NULL;
11208
11209 xmlSchemaPCustomErrExt(ctxt,
11210 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11211 NULL, type, NULL,
11212 "The member type %s is not validly derived from its "
11213 "corresponding member type %s of the base type %s",
11214 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11215 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11216 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11217 FREE_AND_NULL(str)
11218 FREE_AND_NULL(strBMT)
11219 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011220 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11221 }
11222 member = member->next;
11223 baseMember = baseMember->next;
11224 }
11225 }
11226 }
11227 /*
11228 * 3.3.2.4 Only pattern and enumeration facet components are
11229 * allowed among the {facets}.
11230 */
11231 if (type->facets != NULL) {
11232 xmlSchemaFacetPtr facet;
11233 int ok = 1;
11234
11235 facet = type->facets;
11236 do {
11237 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11238 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011239 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11240 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11241 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011242 ok = 0;
11243 }
11244 facet = facet->next;
11245 } while (facet != NULL);
11246 if (ok == 0)
11247 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11248
11249 }
11250 /*
11251 * TODO: 3.3.2.5 (facet derivation)
11252 */
11253 }
11254 }
11255
11256 return (0);
11257}
11258
11259/**
11260 * xmlSchemaCheckSRCSimpleType:
11261 * @ctxt: the schema parser context
11262 * @type: the simple type definition
11263 *
11264 * Checks crc-simple-type constraints.
11265 *
11266 * Returns 0 if the constraints are satisfied,
11267 * if not a positive error code and -1 on internal
11268 * errors.
11269 */
11270static int
11271xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11272 xmlSchemaTypePtr type)
11273{
11274 /*
11275 * NOTE: src-simple-type 2-4 are redundant, since the checks
11276 * were are done for the corresponding <restriction>, <list> and <union>
11277 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11278 * Maby this can be skipped in the future, if we get sure it's not needed.
11279 */
11280 if (type->subtypes == NULL) {
11281 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011282 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011283 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011284 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011285 type->name, NULL);
11286 return (-1);
11287 }
11288 /*
11289 * src-simple-type.1 The corresponding simple type definition, if any,
11290 * must satisfy the conditions set out in Constraints on Simple Type
11291 * Definition Schema Components (§3.14.6).
11292 */
11293 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11294 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11295 /*
11296 * TODO: Removed this, since it got annoying to get an
11297 * extra error report, if anything failed until now.
11298 * Enable this if needed.
11299 */
11300 /*
11301 xmlSchemaPErr(ctxt, type->node,
11302 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011303 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011304 "on simple type definitions.\n",
11305 type->name, NULL);
11306 */
11307 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11308 }
11309
11310 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11311 /*
11312 * src-simple-type.2 If the <restriction> alternative is chosen,
11313 * either it must have a base [attribute] or a <simpleType> among its
11314 * [children], but not both.
11315 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011316 /*
11317 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11318 * NOTE: This was removed, since this will be already handled
11319 * in the parse function for <restriction>.
11320 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011321 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11322 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11323 * an itemType [attribute] or a <simpleType> among its [children],
11324 * but not both.
11325 * NOTE: baseType is set to the local simple type definiton,
11326 * if existent, at parse time. This is a hack and not nice.
11327 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011328 /*
11329 * TODO: Remove this, and add the check to the parse function of <list>.
11330 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011331 if (((type->subtypes->base == NULL) &&
11332 (type->baseType == NULL)) ||
11333 ((type->subtypes->base != NULL) &&
11334 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011335 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011336 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011337 NULL, type, NULL,
11338 "Either the attribute 'itemType' or the <simpleType> child "
11339 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011340 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11341 }
11342
11343
11344 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11345 xmlSchemaTypeLinkPtr member;
11346 xmlSchemaTypePtr ancestor, anySimpleType;
11347
11348 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11349
11350 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11351 * the <union> alternative is chosen, there must not be any entries
11352 * in the memberTypes [attribute] at any depth which resolve to the
11353 * component corresponding to the <simpleType>.
11354 */
11355 member = type->memberTypes;
11356 while (member != NULL) {
11357 ancestor = member->type;
11358 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11359 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11360 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11361 if (ancestor == anySimpleType)
11362 break;
11363 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011364 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011365 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011366 NULL, type, NULL,
11367 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011368 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11369 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11370 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011371 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011372 * type as item type, which in turn has a list ST as member
11373 * type, we will assume this here as well, since this check
11374 * was not yet performed.
11375 */
11376
11377 }
11378 ancestor = ancestor->baseType;
11379 }
11380 member = member->next;
11381 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011382 }
11383
11384 return (0);
11385}
11386
William M. Brack2f2a6632004-08-20 23:09:47 +000011387#if 0 /* Not yet used code for CT schema validation */
11388static int
11389xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11390 const xmlChar * value,
11391 xmlSchemaTypePtr type,
11392 int fireErrors)
11393{
11394 int ret;
11395 /*
11396 * 3.14.4 Simple Type Definition Validation Rules
11397 * Validation Rule: String Valid
11398 */
11399 /*
11400 * 1 It is schema-valid with respect to that definition as defined
11401 * by Datatype Valid in [XML Schemas: Datatypes].
11402 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011403 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11404 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011405 return (ret);
11406 /*
11407 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11408 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11409 * the string must be a ·declared entity name·.
11410 */
11411 /*
11412 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11413 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11414 * then every whitespace-delimited substring of the string must be a ·declared
11415 * entity name·.
11416 */
11417 /*
11418 * 2.3 otherwise no further condition applies.
11419 */
11420
11421 return (0);
11422}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011423#endif
11424
William M. Brack2f2a6632004-08-20 23:09:47 +000011425
11426static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011427xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11428{
11429 if (vctxt->pctxt == NULL) {
11430 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11431 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11432 if (vctxt->pctxt == NULL) {
11433 xmlSchemaVErr(vctxt, NULL,
11434 XML_SCHEMAV_INTERNAL,
11435 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11436 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011437 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011438 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011439 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011440 /* TODO: Pass user data. */
11441 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11442 }
11443 return (0);
11444}
11445
11446static int
11447xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11448{
11449 if (ctxt->vctxt == NULL) {
11450 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11451 if (ctxt->vctxt == NULL) {
11452 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011453 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011454 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11455 "failed to create a temp. validation context.\n",
11456 NULL, NULL);
11457 return (-1);
11458 }
11459 /* TODO: Pass user data. */
11460 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11461 }
11462 return (0);
11463}
11464
11465/**
11466 * xmlSchemaCheckCOSValidDefault:
11467 * @ctxt: the schema parser context
11468 * @type: the simple type definition
11469 * @value: the default value
11470 * @node: an optional node (the holder of the value)
11471 *
11472 * Checks the "cos-valid-default" constraints.
11473 *
11474 * Returns 0 if the constraints are satisfied,
11475 * if not, a positive error code and -1 on internal
11476 * errors.
11477 */
11478static int
11479xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11480 xmlSchemaValidCtxtPtr vctxt,
11481 xmlSchemaTypePtr type,
11482 const xmlChar *value,
11483 xmlNodePtr node)
11484{
11485 int ret = 0;
11486
11487 /*
11488 * cos-valid-default:
11489 * Schema Component Constraint: Element Default Valid (Immediate)
11490 * For a string to be a valid default with respect to a type
11491 * definition the appropriate case among the following must be true:
11492 */
11493 /*
11494 * NOTE: This has to work without a given node (the holder of the
11495 * value), since it should work on the component, i.e. an underlying
11496 * DOM must not be mandatory.
11497 */
11498 if ((pctxt == NULL) || (vctxt == NULL)) {
11499 xmlSchemaPErr(pctxt, node,
11500 XML_SCHEMAP_INTERNAL,
11501 "Internal error: xmlSchemaCheckCOSValidDefault, "
11502 "bad arguments: the parser and/or validation context is "
11503 "missing.\n",
11504 NULL, NULL);
11505 return (-1);
11506 }
11507 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011508 /*
11509 * Complex type.
11510 *
11511 * 2.1 its {content type} must be a simple type definition or mixed.
11512 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011513 /*
11514 * TODO: Adjust this when the content type will be computed
11515 * correctly.
11516 */
11517 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11518 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11519 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11520 xmlSchemaPSimpleTypeErr(pctxt,
11521 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11522 NULL, NULL, node,
11523 type, NULL, NULL,
11524 "If the type of a constraint value is complex, its content "
11525 "type must be mixed or a simple type",
11526 NULL, NULL);
11527 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11528 }
11529 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011530 /*
11531 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11532 * particle must be ·emptiable· as defined by Particle Emptiable
11533 * (§3.9.6).
11534 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011535
William M. Brack2f2a6632004-08-20 23:09:47 +000011536 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011537 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011538 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011539 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011540 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011541 }
11542 /*
11543 * 1 If the type definition is a simple type definition, then the string
11544 * must be ·valid· with respect to that definition as defined by String
11545 * Valid (§3.14.4).
11546 *
11547 * AND
11548 *
11549 * 2.2.1 If the {content type} is a simple type definition, then the
11550 * string must be ·valid· with respect to that simple type definition
11551 * as defined by String Valid (§3.14.4).
11552 */
11553 vctxt->node = node;
11554 vctxt->cur = NULL;
11555 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11556 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11557 if (ret < 0) {
11558 xmlSchemaPErr(pctxt, node,
11559 /* NOTNICE: error code: This function will be used during
11560 * schema construction and xsi:type validation.
11561 */
11562 XML_SCHEMAP_INTERNAL,
11563 "Internal error: xmlSchemaCheckCOSValidDefault, "
11564 "while validating a value constaint value.\n",
11565 NULL, NULL);
11566
11567 }
11568 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011569}
11570
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011571#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011572/**
11573 * xmlSchemaGetSTContentOfCT:
11574 * @ctxt: the schema parser context
11575 * @type: the complex type definition
11576 *
11577 *
11578 * Returns the corresponding simple type for the content of
11579 * the complex type.
11580 */
11581static xmlSchemaTypePtr
11582xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11583 xmlSchemaTypePtr type)
11584{
11585 xmlSchemaTypePtr orig = type, anyType;
11586
11587 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11588 while ((type != NULL) && (type != anyType) &&
11589 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11590 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11591 return(type);
11592 type = type->baseType;
11593 }
11594 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011595 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011596 NULL, orig, NULL,
11597 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11598 "no simple type for the content of complex type '%s' could be "
11599 "computed", orig->name);
11600 return (NULL);
11601}
11602
11603
William M. Brack2f2a6632004-08-20 23:09:47 +000011604
William M. Brack2f2a6632004-08-20 23:09:47 +000011605
11606/**
11607 * xmlSchemaCheckCOSCTExtends:
11608 * @ctxt: the schema parser context
11609 * @type: the complex type definition
11610 *
11611 * Schema Component Constraint: Derivation Valid (Extension)
11612 *
11613 * Returns 0 if the constraints are satisfied, a positive
11614 * error code if not and -1 if an internal error occured.
11615 */
11616static int
11617xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11618 xmlSchemaTypePtr type)
11619{
11620 xmlSchemaTypePtr base;
11621 /*
11622 * 1 If the {base type definition} is a complex type definition,
11623 * then all of the following must be true:
11624 */
11625 base = type->baseType;
11626 if (base == NULL) {
11627 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011628 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011629 NULL, type, NULL,
11630 "Internal error: xmlSchemaCheckCOSCTExtends, "
11631 "the complex type '%s' has no base type", type->name);
11632 return (-1);
11633 }
11634 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11635 /*
11636 * 1.1 The {final} of the {base type definition} must not
11637 * contain extension.
11638 */
11639 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11640 xmlSchemaPCustomErr(ctxt,
11641 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11642 NULL, type, NULL,
11643 "The 'final' of the base type definition "
11644 "contains extension", NULL);
11645 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11646 }
11647 /*
11648 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11649 * of the complex type definition itself, that is, for every attribute
11650 * use in the {attribute uses} of the {base type definition}, there
11651 * must be an attribute use in the {attribute uses} of the complex
11652 * type definition itself whose {attribute declaration} has the same
11653 * {name}, {target namespace} and {type definition} as its attribute
11654 * declaration
11655 *
11656 * NOTE: This will be already satisfied by the way the attribute uses
11657 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11658 * is not needed.
11659 */
11660
11661 /*
11662 * 1.3 If it has an {attribute wildcard}, the complex type definition
11663 * must also have one, and the base type definition's {attribute
11664 * wildcard}'s {namespace constraint} must be a subset of the complex
11665 * type definition's {attribute wildcard}'s {namespace constraint},
11666 * as defined by Wildcard Subset (§3.10.6).
11667 *
11668 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11669 * this check is not needed.
11670 */
11671
11672 /*
11673 * 1.4 One of the following must be true:
11674 *
11675 * 1.4.1 The {content type} of the {base type definition} and the
11676 * {content type} of the complex type definition itself must be the same
11677 * simple type definition
11678 */
11679
11680
11681
11682 } else {
11683 /*
11684 * 2 If the {base type definition} is a simple type definition,
11685 * then all of the following must be true:
11686 */
11687 /*
11688 * 2.1 The {content type} must be the same simple type definition.
11689 */
11690 /*
11691 * 2.2 The {final} of the {base type definition} must not contain
11692 * extension
11693 */
11694 }
11695
11696}
11697
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011698static int
11699xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11700 xmlSchemaTypePtr type)
11701{
11702 xmlSchemaTypePtr base, content;
11703 int OK = 0;
11704
11705 /*
11706 * TODO: Adjust the error codes here, as I used
11707 * XML_SCHEMAP_SRC_CT_1 only yet.
11708 */
11709 /*
11710 * Schema Representation Constraint:
11711 * Complex Type Definition Representation OK
11712 */
11713 base = type->baseType;
11714 if (base == NULL) {
11715 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11716 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11717 type->name);
11718 return (-1);
11719 }
11720
11721 if (type->subtypes != NULL) {
11722 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11723 if IS_COMPLEX_TYPE(base) {
11724 /*
11725 * 1 If the <complexContent> alternative is chosen, the type definition
11726 * ·resolved· to by the ·actual value· of the base [attribute]
11727 * must be a complex type definition;
11728 */
11729 xmlSchemaPCustomErr(ctxt,
11730 XML_SCHEMAP_SRC_CT_1,
11731 NULL, type, NULL,
11732 "The base type is not a complex type", NULL);
11733 return (XML_SCHEMAP_SRC_CT_1);
11734 }
11735 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11736
11737 if IS_SIMPLE_TYPE(base) {
11738 if (type->flags &
11739 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11740 /*
11741 * 2.1.3 only if the <extension> alternative is also
11742 * chosen, a simple type definition.
11743 */
11744 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11745 xmlSchemaPCustomErr(ctxt,
11746 XML_SCHEMAP_SRC_CT_1,
11747 NULL, type, NULL,
11748 "A complex type (simple content) cannot restrict "
11749 "an other simple type",
11750 NULL);
11751 return (XML_SCHEMAP_SRC_CT_1);
11752 }
11753 OK = 1;
11754
11755 } else { /* if IS_SIMPLE_TYPE(base) */
11756 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11757 /*
11758 * 2.1.2 only if the <restriction> alternative is also
11759 * chosen, a complex type definition whose {content type}
11760 * is mixed and a particle emptyable.
11761 */
11762 /*
11763 * FIXME TODO: Check for *empiable particle* is missing.
11764 */
11765 if ((type->flags &
11766 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11767 xmlSchemaPCustomErr(ctxt,
11768 XML_SCHEMAP_SRC_CT_1,
11769 NULL, type, NULL,
11770 "A complex type (simple content) cannot "
11771 "extend an other complex type which has a "
11772 "content type of: 'mixed' and emptiable particle",
11773 NULL);
11774 return (XML_SCHEMAP_SRC_CT_1);
11775 }
11776 /*
11777 * NOTE: This will be fired as well, if the base type
11778 * is *'anyType'*.
11779 * NOTE: type->subtypes->subtypes will be the
11780 * <restriction> item.
11781 */
11782 if (type->subtypes->subtypes == NULL) {
11783 /* Yes, this is paranoid programming. */
11784 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11785 NULL, type, NULL,
11786 "Internal error: xmlSchemaCheckSRCCT, "
11787 "'%s', <simpleContent> has no <restriction>",
11788 type->name);
11789 return (-1);
11790 }
11791 /*
11792 * 2.2 If clause 2.1.2 above is satisfied, then there
11793 * must be a <simpleType> among the [children] of
11794 * <restriction>.
11795 */
11796 if (type->subtypes->subtypes->type !=
11797 XML_SCHEMA_TYPE_SIMPLE) {
11798 /* TODO: Change error code to ..._SRC_CT_2_2. */
11799 xmlSchemaPCustomErr(ctxt,
11800 XML_SCHEMAP_SRC_CT_1,
11801 NULL, type, NULL,
11802 "A <simpleType> is expected among the children "
11803 "of <restriction>", NULL);
11804 return (XML_SCHEMAP_SRC_CT_1);
11805 }
11806 OK = 1;
11807 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
11808 /*
11809 * 2.1.1 a complex type definition whose {content type} is a
11810 * simple type definition;
11811 */
11812 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
11813 xmlSchemaPCustomErr(ctxt,
11814 XML_SCHEMAP_SRC_CT_1,
11815 NULL, type, NULL,
11816 "A complex type (simple content) cannot "
11817 "be derived from the complex type '%s'",
11818 base->name);
11819 return (XML_SCHEMAP_SRC_CT_1);
11820 }
11821 content = base->contentTypeDef;
11822 if (content == NULL) {
11823 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11824 NULL, type, NULL,
11825 "Internal error: xmlSchemaCheckSRCCT, "
11826 "'%s', base type has no content type",
11827 type->name);
11828 return (-1);
11829 }
11830 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
11831 xmlSchemaPCustomErr(ctxt,
11832 XML_SCHEMAP_SRC_CT_1,
11833 NULL, type, NULL,
11834 "A complex type (simple content) cannot "
11835 "be derived from the complex type '%s'",
11836 base->name);
11837 return (XML_SCHEMAP_SRC_CT_1);
11838 }
11839 }
11840 }
11841 }
11842 }
11843 /*
11844 * TODO: 3 The corresponding complex type definition component must
11845 * satisfy the conditions set out in Constraints on Complex Type
11846 * Definition Schema Components (§3.4.6);
11847 *
11848 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
11849 * above for {attribute wildcard} is satisfied, the intensional
11850 * intersection must be expressible, as defined in Attribute Wildcard
11851 * Intersection (§3.10.6).
11852 */
11853
11854}
William M. Brack2f2a6632004-08-20 23:09:47 +000011855#endif
11856
Daniel Veillard01fa6152004-06-29 17:04:39 +000011857/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011858 * xmlSchemaGroupDefFixup:
11859 * @typeDecl: the schema model group definition
11860 * @ctxt: the schema parser context
11861 *
11862 * Fixes model group definitions.
11863 */
11864static void
11865xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11866 xmlSchemaParserCtxtPtr ctxt,
11867 const xmlChar * name ATTRIBUTE_UNUSED)
11868{
11869 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11870 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11871 xmlSchemaTypePtr groupDef;
11872 /*
11873 * Resolve the reference.
11874 */
11875 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11876 group->refNs);
11877 if (groupDef == NULL) {
11878 xmlSchemaPResCompAttrErr(ctxt,
11879 XML_SCHEMAP_SRC_RESOLVE,
11880 NULL, group, NULL,
11881 "ref", group->ref, group->refNs,
11882 XML_SCHEMA_TYPE_GROUP, NULL);
11883 return;
11884 }
11885 group->subtypes = groupDef;
11886 }
11887}
11888
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011889#if 0 /* Enable when the content type will be computed. */
11890static int
11891xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
11892 xmlSchemaTypePtr type)
11893{
11894 xmlSchemaTypePtr base, res = NULL;
11895
11896 base = type->baseType;
11897 if (base == NULL) {
11898 xmlSchemaPCustomErr(ctxt,
11899 XML_SCHEMAP_INTERNAL,
11900 NULL, type, NULL,
11901 "Internal error: xmlSchemaGetContentType, "
11902 "the complex type '%s' has no base type", type->name);
11903 return (-1);
11904 }
11905 if (IS_ANYTYPE(base) || (type->subtypes->type ==
11906 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
11907 xmlSchemaTypePtr start;
11908 /*
11909 * Effective 'mixed'.
11910 */
11911 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
11912 type->contentType = XML_SCHEMA_CONTENT_MIXED;
11913 /*
11914 * Effective content.
11915 */
11916 if (IS_ANYTYPE(base))
11917 start = type;
11918 else
11919 start = type->subtypes;
11920
11921 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
11922 xmlSchemaTypePtr baseContentItem;
11923
11924 /*
11925 * Complex type with simple content.
11926 */
11927 if IS_COMPLEX_TYPE(base) {
11928 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11929 /*
11930 * Summary: a complex type (simple content) can *restrict*
11931 * a complex type with the following content type:
11932 * 1. 'mixed' and an emptiable particle
11933 * 2. simple type
11934 */
11935 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
11936 /*
11937 * 2 if the {content type} of the base type is mixed and a
11938 * particle which is ·emptiable·,
11939 * [...]
11940 * then starting from the simple type definition
11941 * corresponding to the <simpleType> among the [children]
11942 * of <restriction> (**which must be present**)
11943 *
11944 * FIXME TODO: Handle "emptiable particle".
11945 */
11946 res = type->subtypes->subtypes;
11947 if (res == NULL) {
11948 xmlSchemaPCustomErr(ctxt,
11949 XML_SCHEMAP_INTERNAL,
11950 NULL, type, NULL,
11951 "Internal error: xmlSchemaGetContentType, "
11952 "CT '%s' (restricting): <simpleContent> has no "
11953 "<restriction>",
11954 type->name);
11955 return (-1);
11956 }
11957
11958 res->subtypes;
11959 if (res == NULL) {
11960 xmlSchemaPCustomErr(ctxt,
11961 XML_SCHEMAP_INTERNAL,
11962 NULL, type, NULL,
11963 "Internal error: xmlSchemaGetContentType, "
11964 "CT '%s' (restricting): <restriction> has no "
11965 "mandatory <simpleType>",
11966 type->name);
11967 return (-1);
11968 }
11969 } else {
11970 baseContentItem = base->contentTypeDef;
11971 if (baseContentItem == NULL) {
11972 xmlSchemaPCustomErr(ctxt,
11973 XML_SCHEMAP_INTERNAL,
11974 NULL, type, NULL,
11975 "Internal error: xmlSchemaGetContentType, "
11976 "CT '%s' (restricting), the base type has no "
11977 "content type", type->name);
11978 return (-1);
11979 }
11980 if IS_SIMPLE_TYPE(baseContentItem) {
11981 /*
11982 * 1 If the base type is a complex type whose own
11983 * {content type} is a simple type and the <restriction>
11984 * alternative is chosen
11985 */
11986 /* type->subtypes->subtypes will be the restriction item.*/
11987 res = type->subtypes->subtypes;
11988 if (res == NULL) {
11989 xmlSchemaPCustomErr(ctxt,
11990 XML_SCHEMAP_INTERNAL,
11991 NULL, type, NULL,
11992 "Internal error: xmlSchemaGetContentType, "
11993 "CT '%s' (restricting): <simpleType> has no "
11994 "<restriction>", type->name);
11995 return (-1);
11996 }
11997 /*
11998 * 1.1 the simple type definition corresponding to the
11999 * <simpleType> among the [children] of <restriction>if
12000 * there is one;
12001 */
12002 res = res->subtypes;
12003 if (res == NULL) {
12004 /*
12005 * 1.2 otherwise the {content type}
12006 * of the base type .
12007 */
12008 res = baseContentItem;
12009 }
12010 }
12011 }
12012 /*
12013 * SPECIAL TODO: If *restricting* the spec wants us to
12014 * create an *additional* simple type which restricts the
12015 * located simple type; we won't do this yet, and look how
12016 * far we get with it.
12017 */
12018 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12019 /*
12020 * Summary: a complex type (simple content) can *extend*
12021 * only a complex base with a simple type as content.
12022 */
12023 /*
12024 * 3 If the type definition ·resolved· to by the ·actual
12025 * value· of the base [attribute] is a complex type
12026 * definition (whose own {content type} *must be* a simple
12027 * type definition, see below) and the *<extension>*
12028 * alternative is chosen, then the {content type} of that
12029 * complex type definition;
12030 */
12031 res = base->contentTypeDef;
12032 if (res == NULL) {
12033 xmlSchemaPCustomErr(ctxt,
12034 XML_SCHEMAP_INTERNAL,
12035 NULL, type, NULL,
12036 "Internal error: xmlSchemaGetContentType, "
12037 "CT '%s' (extending), the base type has no content "
12038 "type", type->name);
12039 return (-1);
12040 }
12041 if (! IS_SIMPLE_TYPE(res)) {
12042 xmlSchemaPCustomErr(ctxt,
12043 XML_SCHEMAP_INTERNAL,
12044 NULL, type, NULL,
12045 "Internal error: xmlSchemaGetContentType, "
12046 "CT '%s' (extending), the content type of the "
12047 "base is not a simple type", type->name);
12048 return (-1);
12049 }
12050 }
12051 } else /* if IS_COMPLEX_TYPE(base) */
12052 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12053 /*
12054 * 4 otherwise (the type definition ·resolved· to by the
12055 * ·actual value· of the base [attribute] is a simple type
12056 * definition and the <extension> alternative is chosen),
12057 * then that simple type definition.
12058 */
12059 res = base;
12060 }
12061 type->contentTypeDef = res;
12062 if (res == NULL) {
12063 xmlSchemaPCustomErr(ctxt,
12064 XML_SCHEMAP_INTERNAL,
12065 NULL, type, NULL,
12066 "Internal error: xmlSchemaGetContentType, "
12067 "'%s', the content type could not be determined",
12068 type->name);
12069 return (-1);
12070 }
12071
12072 }
12073
12074}
12075#endif
12076
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012077/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012078 * xmlSchemaTypeFixup:
12079 * @typeDecl: the schema type definition
12080 * @ctxt: the schema parser context
12081 *
12082 * Fixes the content model of the type.
12083 */
12084static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012085xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012086 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012087{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012088 xmlSchemaTypePtr ctxtType;
12089
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012090 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012091 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012092 /*
12093 * Do not allow the following types to be typefixed, prior to
12094 * the corresponding simple/complex types.
12095 */
12096 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012097 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012098 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12099 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12100 case XML_SCHEMA_TYPE_UNION:
12101 case XML_SCHEMA_TYPE_RESTRICTION:
12102 case XML_SCHEMA_TYPE_EXTENSION:
12103 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012104 default:
12105 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012106 }
12107 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012108 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012109 name = item->name;
12110 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12111 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012112 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012113 if (item->subtypes != NULL) {
12114 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012115 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012116 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012117 NULL);
12118 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012119 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012120 XML_SCHEMA_CONTENT_SIMPLE;
12121 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012122 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012123 break;
12124 }
12125 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012126 xmlSchemaTypePtr base = NULL;
12127
12128 ctxt->ctxtType->flags |=
12129 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012130 if (item->baseType != NULL)
12131 base = item->baseType;
12132 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012133 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012134 xmlSchemaGetType(ctxt->schema, item->base,
12135 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012136 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012137 xmlSchemaPResCompAttrErr(ctxt,
12138 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012139 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012140 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12141 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012142 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012143 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012144 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012145 xmlSchemaTypeFixup(base, ctxt, NULL);
12146 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012147 }
12148 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012149 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12150 /*
12151 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012152 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012153 /*
12154 * Content type.
12155 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012156 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012157 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012158 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12159 else if ((item->subtypes->subtypes == NULL) &&
12160 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012161 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012162 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012163 XML_SCHEMA_TYPE_SEQUENCE)))
12164 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012165 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12166 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012167 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012168 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012169 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012170 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012171 else {
12172 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012173 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012174 XML_SCHEMA_CONTENT_ELEMENTS;
12175 }
12176 } else {
12177 /*
12178 * SimpleType restriction.
12179 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012180 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012181 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012182 break;
12183 }
12184 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012185 xmlSchemaTypePtr base = NULL;
12186 xmlSchemaContentType explicitContentType;
12187
12188 /*
12189 * An extension does exist on a complexType only.
12190 */
12191 ctxt->ctxtType->flags |=
12192 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012193 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012194 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012195 xmlSchemaPCustomErr(ctxt,
12196 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012197 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012198 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012199 return;
12200 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012201 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012202 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012203 xmlSchemaGetType(ctxt->schema, item->base,
12204 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012205 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012206 xmlSchemaPResCompAttrErr(ctxt,
12207 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012208 NULL, item, item->node,
12209 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012210 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012211 } else if (base->contentType ==
12212 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012213 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012214 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012215 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012216 }
12217 /*
12218 * The type definition ·resolved· to by the ·actual
12219 * value· of the base [attribute]
12220 */
12221 ctxt->ctxtType->baseType = base;
12222 /*
12223 * TODO: This one is still needed for computation of
12224 * the content model by xmlSchemaBuildAContentModel.
12225 * Try to get rid of it.
12226 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012227 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012228 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012229 if ((item->subtypes != NULL) &&
12230 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12231 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012232
12233 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012234 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012235 /* 1.1.1 */
12236 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012237 else if ((item->subtypes->subtypes == NULL) &&
12238 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012239 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012240 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012241 XML_SCHEMA_TYPE_SEQUENCE)))
12242 /* 1.1.2 */
12243 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012244 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012245 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012246 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012247 /* 1.1.3 */
12248 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12249 if (base != NULL) {
12250 /* It will be reported later, if the base is missing. */
12251 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12252 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012253 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012254 } else if (base->contentType ==
12255 XML_SCHEMA_CONTENT_EMPTY) {
12256 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012257 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012258 XML_SCHEMA_CONTENT_ELEMENTS;
12259 } else {
12260 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012261 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012262 XML_SCHEMA_CONTENT_ELEMENTS;
12263 }
12264 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012265 break;
12266 }
12267 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012268 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012269 ctxt->ctxtType = item;
12270 /*
12271 * Start with an empty content-type type.
12272 */
12273 if (item->subtypes == NULL)
12274 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12275
12276 if ((item->subtypes == NULL) ||
12277 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012278 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012279 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012280 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12281 /*
12282 * This case is understood as shorthand for complex
12283 * content restricting the ur-type definition, and
12284 * the details of the mappings should be modified as
12285 * necessary.
12286 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012287 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12288 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012289 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012290 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012291 * Assume that we inherit the content-type type
12292 * from 'anyType', which is 'mixed' and a particle
12293 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012294 */
12295 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012296 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012297 /*
12298 * Fixup the sub components.
12299 */
12300 if ((item->subtypes != NULL) &&
12301 (item->subtypes->contentType ==
12302 XML_SCHEMA_CONTENT_UNKNOWN)) {
12303 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012304 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012305 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12306 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12307 } else if (item->subtypes != NULL) {
12308 /*
12309 * Use the content-type type of the model groups
12310 * defined, if 'mixed' is not set. If 'mixed' is set
12311 * it will expand the content-type by allowing character
12312 * content to appear.
12313 */
12314 item->contentType =
12315 item->subtypes->contentType;
12316 }
12317 xmlSchemaBuildAttributeValidation(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012318 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012319 break;
12320 }
12321 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012322 if (item->subtypes == NULL) {
12323 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12324 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12325 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012326 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012327 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012328 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12329 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012330 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012331 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012332 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012333 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012334 if (item->subtypes != NULL)
12335 item->contentType =
12336 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012337 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012338 /*
12339 * Removed due to implementation of the build of attribute uses.
12340 */
12341 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012342 if (item->attributes == NULL)
12343 item->attributes =
12344 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012345 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012346 }
12347 break;
12348 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012349 case XML_SCHEMA_TYPE_SIMPLE:
12350 /*
12351 * Simple Type Definition Schema Component
12352 *
12353 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012354 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012355 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12356 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012357 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012358 ctxt->ctxtType = item;
12359 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012360 }
12361 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012362 if ((item->baseType != NULL) &&
12363 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 XML_SCHEMA_CONTENT_UNKNOWN)) {
12365 /* OPTIMIZE: Actually this one will never by hit, since
12366 * the base type is already type-fixed in <restriction>.
12367 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012368 ctxt->ctxtType = item;
12369 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012370 }
12371 /* Base type:
12372 * 2 If the <list> or <union> alternative is chosen,
12373 * then the ·simple ur-type definition·.
12374 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012375 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012376 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012377 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12378 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12379 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012380 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012381 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12382 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12383 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012384 XML_SCHEMA_TYPE_RESTRICTION) {
12385 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12386
12387 /*
12388 * Variety
12389 * If the <restriction> alternative is chosen, then the
12390 * {variety} of the {base type definition}.
12391 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012392 if (item->baseType != NULL) {
12393 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012394 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012395 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12396 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012397 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012398 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12399 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012400 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012401 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012402 /*
12403 * Schema Component Constraint: Simple Type Restriction
12404 * (Facets)
12405 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12406 * applied beforehand.
12407 *
12408 * 3 The {facets} of R are the union of S and the {facets}
12409 * of B, eliminating duplicates. To eliminate duplicates,
12410 * when a facet of the same kind occurs in both S and the
12411 * {facets} of B, the one in the {facets} of B is not
12412 * included, with the exception of enumeration and pattern
12413 * facets, for which multiple occurrences with distinct values
12414 * are allowed.
12415 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 if (item->baseType->facetSet != NULL) {
12417 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012418 if (last != NULL)
12419 while (last->next != NULL)
12420 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012421 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012422 for (; cur != NULL; cur = cur->next) {
12423 /*
12424 * Base patterns won't be add here:
12425 * they are ORed in a type and
12426 * ANDed in derived types. This will
12427 * happed at validation level by
12428 * walking the base axis of the type.
12429 */
12430 if (cur->facet->type ==
12431 XML_SCHEMA_FACET_PATTERN)
12432 continue;
12433 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012434 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012435 (cur->facet->type !=
12436 XML_SCHEMA_FACET_PATTERN) &&
12437 (cur->facet->type !=
12438 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012439 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012440 do {
12441 if (cur->facet->type ==
12442 facet->facet->type)
12443 break;
12444 facet = facet->next;
12445 } while (facet != NULL);
12446 }
12447 if (facet == NULL) {
12448 facet = (xmlSchemaFacetLinkPtr)
12449 xmlMalloc(sizeof(xmlSchemaFacetLink));
12450 if (facet == NULL) {
12451 xmlSchemaPErrMemory(ctxt,
12452 "fixing simpleType", NULL);
12453 return;
12454 }
12455 facet->facet = cur->facet;
12456 facet->next = NULL;
12457 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012458 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012459 else
12460 last->next = facet;
12461 last = facet;
12462 }
12463 }
12464 }
12465 }
12466 }
12467 /*
12468 * Check constraints.
12469 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012470 xmlSchemaCheckSRCSimpleType(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012471 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012472 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012473 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012474 case XML_SCHEMA_TYPE_ALL:
12475 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012476 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012477 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012478 case XML_SCHEMA_TYPE_GROUP:
12479 /*
12480 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12481 */
12482 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012483 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012484 xmlSchemaParseListRefFixup(item, ctxt);
12485 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012486 break;
12487 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012488 xmlSchemaParseUnionRefCheck(item, ctxt);
12489 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012490 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012491 case XML_SCHEMA_TYPE_BASIC:
12492 case XML_SCHEMA_TYPE_ANY:
12493 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012494 case XML_SCHEMA_TYPE_UR:
12495 case XML_SCHEMA_TYPE_ELEMENT:
12496 case XML_SCHEMA_TYPE_ATTRIBUTE:
12497 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012498 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012499 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012500 case XML_SCHEMA_FACET_MININCLUSIVE:
12501 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12502 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12503 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12504 case XML_SCHEMA_FACET_TOTALDIGITS:
12505 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12506 case XML_SCHEMA_FACET_PATTERN:
12507 case XML_SCHEMA_FACET_ENUMERATION:
12508 case XML_SCHEMA_FACET_WHITESPACE:
12509 case XML_SCHEMA_FACET_LENGTH:
12510 case XML_SCHEMA_FACET_MAXLENGTH:
12511 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012512 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12513 if (item->subtypes != NULL)
12514 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012515 break;
12516 }
12517 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012518#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012519 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012520 xmlGenericError(xmlGenericErrorContext,
12521 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012522 item->node->doc->URL,
12523 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012524 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012525 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012526 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012527 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012528 case XML_SCHEMA_CONTENT_SIMPLE:
12529 xmlGenericError(xmlGenericErrorContext, "simple\n");
12530 break;
12531 case XML_SCHEMA_CONTENT_ELEMENTS:
12532 xmlGenericError(xmlGenericErrorContext, "elements\n");
12533 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012534 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012535 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12536 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012537 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012538 xmlGenericError(xmlGenericErrorContext, "empty\n");
12539 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012540 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012541 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12542 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012543 /* Removed, since not used. */
12544 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012545 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012546 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12547 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012548 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012549 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012550 xmlGenericError(xmlGenericErrorContext, "basic\n");
12551 break;
12552 default:
12553 xmlGenericError(xmlGenericErrorContext,
12554 "not registered !!!\n");
12555 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012556 }
12557#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012558}
12559
12560/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012561 * xmlSchemaCheckFacet:
12562 * @facet: the facet
12563 * @typeDecl: the schema type definition
12564 * @ctxt: the schema parser context or NULL
12565 * @name: name of the type
12566 *
12567 * Checks the default values types, especially for facets
12568 *
12569 * Returns 0 if okay or -1 in cae of error
12570 */
12571int
12572xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012573 xmlSchemaTypePtr typeDecl,
12574 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012575{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012576 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012577 int ret = 0, reuseValCtxt = 0;
12578
Daniel Veillardce682bc2004-11-05 17:22:25 +000012579 if ((facet == NULL) || (typeDecl == NULL))
12580 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012581 /*
12582 * TODO: will the parser context be given if used from
12583 * the relaxNG module?
12584 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012585
12586 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012587 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012588 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012589 }
12590 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012591 case XML_SCHEMA_FACET_MININCLUSIVE:
12592 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12593 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012594 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12595 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012596 /*
12597 * Okay we need to validate the value
12598 * at that point.
12599 */
12600 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012601 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012602
12603 /* 4.3.5.5 Constraints on enumeration Schema Components
12604 * Schema Component Constraint: enumeration valid restriction
12605 * It is an ·error· if any member of {value} is not in the
12606 * ·value space· of {base type definition}.
12607 *
12608 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12609 * The value ·must· be in the
12610 * ·value space· of the ·base type·.
12611 */
12612 /*
12613 * This function is intended to deliver a compiled value
12614 * on the facet. In XML Schemas the type holding a facet,
12615 * cannot be a built-in type. Thus to ensure that other API
12616 * calls (relaxng) do work, if the given type is a built-in
12617 * type, we will assume that the given built-in type *is
12618 * already* the base type.
12619 */
12620 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12621 base = typeDecl->baseType;
12622 if (base == NULL) {
12623 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012624 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012625 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012626 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012627 typeDecl->name, NULL);
12628 return (-1);
12629 }
12630 } else
12631 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012632 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012633 * This avoids perseverative creation of the
12634 * validation context if a parser context is
12635 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012636 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012637 if (ctxt != NULL) {
12638 reuseValCtxt = 1;
12639 if (ctxt->vctxt == NULL) {
12640 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12641 return (-1);
12642 }
12643 vctxt = ctxt->vctxt;
12644 } else {
12645 vctxt = xmlSchemaNewValidCtxt(NULL);
12646 if (vctxt == NULL) {
12647 xmlSchemaPErr(ctxt, typeDecl->node,
12648 XML_SCHEMAP_INTERNAL,
12649 "Internal error: xmlSchemaCheckFacet, "
12650 "creating a new validation context.\n",
12651 NULL, NULL);
12652 return (-1);
12653 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012654 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012655
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012656 vctxt->node = facet->node;
12657 vctxt->cur = NULL;
12658 /*
12659 * NOTE: This call does not check the content nodes,
12660 * since they are not available:
12661 * facet->node is just the node holding the facet
12662 * definition, *not* the attribute holding the *value*
12663 * of the facet.
12664 */
12665 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12666 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012667 facet->val = vctxt->value;
12668 vctxt->value = NULL;
12669 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012670 /* error code */
12671 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012672 xmlSchemaPErrExt(ctxt, facet->node,
12673 XML_SCHEMAP_INVALID_FACET,
12674 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012675 "Type definition '%s': The value '%s' of the "
12676 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012677 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012678 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012679 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012680 }
12681 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012682 } else if (ret < 0) {
12683 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012684 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012685 NULL, NULL, NULL,
12686 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012687 "failed to validate the value '%s' name of the "
12688 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012689 facet->value,
12690 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12691 base->name, NULL, NULL);
12692 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012693 }
12694 if (reuseValCtxt == 0)
12695 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012696 break;
12697 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012698 case XML_SCHEMA_FACET_PATTERN:
12699 facet->regexp = xmlRegexpCompile(facet->value);
12700 if (facet->regexp == NULL) {
12701 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012702 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012703 "Type definition '%s': The value '%s' of the "
12704 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012705 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012706 ret = -1;
12707 }
12708 break;
12709 case XML_SCHEMA_FACET_TOTALDIGITS:
12710 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12711 case XML_SCHEMA_FACET_LENGTH:
12712 case XML_SCHEMA_FACET_MAXLENGTH:
12713 case XML_SCHEMA_FACET_MINLENGTH:{
12714 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012715
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012716 tmp =
12717 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12718 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012719 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012720 if (tmp != 0) {
12721 /* error code */
12722 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012723 xmlSchemaPErrExt(ctxt, facet->node,
12724 XML_SCHEMAP_INVALID_FACET_VALUE,
12725 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012726 "Type definition '%s': The value '%s' of the "
12727 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012728 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012729 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012730 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012731 }
12732 ret = -1;
12733 }
12734 break;
12735 }
12736 case XML_SCHEMA_FACET_WHITESPACE:{
12737 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12738 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12739 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12740 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12741 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12742 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12743 } else {
12744 if (ctxt != NULL) {
12745 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012746 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012747 "Type definition '%s': The value '%s' of the "
12748 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012749 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012750 }
12751 ret = -1;
12752 }
12753 }
12754 default:
12755 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012756 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012757 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012758}
12759
12760/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012761 * xmlSchemaCheckDefaults:
12762 * @typeDecl: the schema type definition
12763 * @ctxt: the schema parser context
12764 *
12765 * Checks the default values types, especially for facets
12766 */
12767static void
12768xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012769 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012770{
Daniel Veillard4255d502002-04-16 15:50:10 +000012771 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012772 name = typeDecl->name;
12773 /*
12774 * NOTE: It is intended to use the facets list, instead
12775 * of facetSet.
12776 */
12777 if (typeDecl->facets != NULL) {
12778 xmlSchemaFacetPtr facet = typeDecl->facets;
12779
12780 while (facet != NULL) {
12781 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12782 facet = facet->next;
12783 }
12784 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012785}
12786
12787/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012788 * xmlSchemaGetCircModelGrDefRef:
12789 * @ctxtGr: the searched model group
12790 * @list: the list of model groups to be processed
12791 *
12792 * This one is intended to be used by
12793 * xmlSchemaCheckGroupDefCircular only.
12794 *
12795 * Returns the circular model group definition reference, otherwise NULL.
12796 */
12797static xmlSchemaTypePtr
12798xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12799 xmlSchemaTypePtr gr)
12800{
12801 xmlSchemaTypePtr circ = NULL;
12802 int marked;
12803 /*
12804 * We will search for an model group reference which
12805 * references the context model group definition.
12806 */
12807 while (gr != NULL) {
12808 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
12809 (gr->type == XML_SCHEMA_TYPE_ALL) ||
12810 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
12811 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
12812 (gr->subtypes != NULL)) {
12813 marked = 0;
12814 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
12815 (gr->ref != NULL)) {
12816 if (gr->subtypes == ctxtGrDef)
12817 return (gr);
12818 else if (gr->subtypes->flags &
12819 XML_SCHEMAS_TYPE_MARKED) {
12820 gr = gr->next;
12821 continue;
12822 } else {
12823 /*
12824 * Mark to avoid infinite recursion on
12825 * circular references not yet examined.
12826 */
12827 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
12828 marked = 1;
12829 }
12830 if (gr->subtypes->subtypes != NULL)
12831 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12832 gr->subtypes->subtypes);
12833 /*
12834 * Unmark the visited model group definition.
12835 */
12836 if (marked)
12837 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
12838 if (circ != NULL)
12839 return (circ);
12840 } else {
12841 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12842 (xmlSchemaTypePtr) gr->subtypes);
12843 if (circ != NULL)
12844 return (circ);
12845 }
12846
12847 }
12848 gr = gr->next;
12849 }
12850 return (NULL);
12851}
12852
12853/**
12854 * xmlSchemaCheckGroupDefCircular:
12855 * attrGr: the model group definition
12856 * @ctxt: the parser context
12857 * @name: the name
12858 *
12859 * Checks for circular references to model group definitions.
12860 */
12861static void
12862xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
12863 xmlSchemaParserCtxtPtr ctxt,
12864 const xmlChar * name ATTRIBUTE_UNUSED)
12865{
12866 /*
12867 * Schema Component Constraint: Model Group Correct
12868 * 2 Circular groups are disallowed. That is, within the {particles}
12869 * of a group there must not be at any depth a particle whose {term}
12870 * is the group itself.
12871 */
12872 /*
12873 * NOTE: "gr->subtypes" holds the referenced group.
12874 */
12875 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
12876 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
12877 (modelGrDef->subtypes == NULL))
12878 return;
12879 else {
12880 xmlSchemaTypePtr circ;
12881
12882 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
12883 if (circ != NULL) {
12884 /*
12885 * TODO: Report the referenced attr group as QName.
12886 */
12887 xmlSchemaPCustomErr(ctxt,
12888 XML_SCHEMAP_MG_PROPS_CORRECT_2,
12889 NULL, NULL, circ->node,
12890 "Circular reference to the model group definition '%s' "
12891 "defined", modelGrDef->name);
12892 /*
12893 * NOTE: We will cut the reference to avoid further
12894 * confusion of the processor.
12895 * TODO: SPEC: Does the spec define how to process here?
12896 */
12897 circ->subtypes = NULL;
12898 }
12899 }
12900}
12901
12902
12903/**
12904 * xmlSchemaGetCircAttrGrRef:
12905 * @ctxtGr: the searched attribute group
12906 * @attr: the current attribute list to be processed
12907 *
12908 * This one is intended to be used by
12909 * xmlSchemaCheckSRCAttributeGroupCircular only.
12910 *
12911 * Returns the circular attribute grou reference, otherwise NULL.
12912 */
12913static xmlSchemaAttributeGroupPtr
12914xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
12915 xmlSchemaAttributePtr attr)
12916{
12917 xmlSchemaAttributeGroupPtr circ = NULL, gr;
12918 int marked;
12919 /*
12920 * We will search for an attribute group reference which
12921 * references the context attribute group.
12922 */
12923 while (attr != NULL) {
12924 marked = 0;
12925 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12926 gr = (xmlSchemaAttributeGroupPtr) attr;
12927 if (gr->refItem != NULL) {
12928 if (gr->refItem == ctxtGr)
12929 return (gr);
12930 else if (gr->refItem->flags &
12931 XML_SCHEMAS_ATTRGROUP_MARKED) {
12932 attr = attr->next;
12933 continue;
12934 } else {
12935 /*
12936 * Mark as visited to avoid infinite recursion on
12937 * circular references not yet examined.
12938 */
12939 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
12940 marked = 1;
12941 }
12942 }
12943 if (gr->attributes != NULL)
12944 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
12945 /*
12946 * Unmark the visited group's attributes.
12947 */
12948 if (marked)
12949 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
12950 if (circ != NULL)
12951 return (circ);
12952 }
12953 attr = attr->next;
12954 }
12955 return (NULL);
12956}
12957
12958/**
12959 * xmlSchemaCheckSRCAttributeGroupCircular:
12960 * attrGr: the attribute group definition
12961 * @ctxt: the parser context
12962 * @name: the name
12963 *
12964 * Checks for circular references of attribute groups.
12965 */
12966static void
12967xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
12968 xmlSchemaParserCtxtPtr ctxt,
12969 const xmlChar * name ATTRIBUTE_UNUSED)
12970{
12971 /*
12972 * Schema Representation Constraint:
12973 * Attribute Group Definition Representation OK
12974 * 3 Circular group reference is disallowed outside <redefine>.
12975 * That is, unless this element information item's parent is
12976 * <redefine>, then among the [children], if any, there must
12977 * not be an <attributeGroup> with ref [attribute] which resolves
12978 * to the component corresponding to this <attributeGroup>. Indirect
12979 * circularity is also ruled out. That is, when QName resolution
12980 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
12981 * any <attributeGroup>s with a ref [attribute] among the [children],
12982 * it must not be the case that a ·QName· is encountered at any depth
12983 * which resolves to the component corresponding to this <attributeGroup>.
12984 */
12985 /*
12986 * Only global components can be referenced.
12987 */
12988 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
12989 (attrGr->attributes == NULL))
12990 return;
12991 else {
12992 xmlSchemaAttributeGroupPtr circ;
12993
12994 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
12995 if (circ != NULL) {
12996 /*
12997 * TODO: Report the referenced attr group as QName.
12998 */
12999 xmlSchemaPCustomErr(ctxt,
13000 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13001 NULL, NULL, circ->node,
13002 "Circular reference to the attribute group '%s' "
13003 "defined", attrGr->name);
13004 /*
13005 * NOTE: We will cut the reference to avoid further
13006 * confusion of the processor.
13007 * BADSPEC: The spec should define how to process in this case.
13008 */
13009 circ->attributes = NULL;
13010 circ->refItem = NULL;
13011 }
13012 }
13013}
13014
13015/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013016 * xmlSchemaAttrGrpFixup:
13017 * @attrgrpDecl: the schema attribute definition
13018 * @ctxt: the schema parser context
13019 * @name: the attribute name
13020 *
13021 * Fixes finish doing the computations on the attributes definitions
13022 */
13023static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013024xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013025 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013026{
13027 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013028 name = attrgrp->name;
13029 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013030 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013031 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013032 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013033
Daniel Veillardc0826a72004-08-10 14:17:33 +000013034 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13035 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013036 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013037 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013038 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013039 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13040 "ref", attrgrp->ref, attrgrp->refNs,
13041 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013042 return;
13043 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013044 attrgrp->refItem = ref;
13045 /*
13046 * Check for self reference!
13047 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013048 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013049 attrgrp->attributes = ref->attributes;
13050 attrgrp->attributeWildcard = ref->attributeWildcard;
13051 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013052}
13053
13054/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013055 * xmlSchemaAttrCheckValConstr:
13056 * @item: an schema attribute declaration/use
13057 * @ctxt: a schema parser context
13058 * @name: the name of the attribute
13059 *
13060 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013061 *
13062 * Fixes finish doing the computations on the attributes definitions
13063 */
13064static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013065xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13066 xmlSchemaParserCtxtPtr ctxt,
13067 const xmlChar * name ATTRIBUTE_UNUSED)
13068{
13069
13070 /*
13071 * a-props-correct
13072 * Schema Component Constraint: Attribute Declaration Properties Correct
13073 *
13074 * 2 if there is a {value constraint}, the canonical lexical
13075 * representation of its value must be ·valid· with respect
13076 * to the {type definition} as defined in String Valid (§3.14.4).
13077 */
13078
13079 if (item->defValue != NULL) {
13080 int ret;
13081 xmlNodePtr node;
13082 xmlSchemaTypePtr type;
13083
13084 if (item->subtypes == NULL) {
13085 xmlSchemaPErr(ctxt, item->node,
13086 XML_SCHEMAP_INTERNAL,
13087 "Internal error: xmlSchemaCheckAttrValConstr, "
13088 "type is missing... skipping validation of "
13089 "value constraint", NULL, NULL);
13090 return;
13091 }
13092
13093 /*
13094 * TODO: Try to avoid creating a new context.
13095 * TODO: This all is not very performant.
13096 */
13097 type = item->subtypes;
13098 /*
13099 * Ensure there's validation context.
13100 */
13101 if (ctxt->vctxt == NULL) {
13102 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13103 xmlSchemaPErr(ctxt, item->node,
13104 XML_SCHEMAP_INTERNAL,
13105 "Internal error: xmlSchemaCheckAttrValConstr, "
13106 "creating a new validation context.\n",
13107 NULL, NULL);
13108 return;
13109 }
13110 }
13111
13112 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13113 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13114 else
13115 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13116 ctxt->vctxt->node = node;
13117 ctxt->vctxt->cur = NULL;
13118 /*
13119 * NOTE: This call does not check the content nodes,
13120 * since they are not available:
13121 * facet->node is just the node holding the facet
13122 * definition, *not* the attribute holding the *value*
13123 * of the facet.
13124 */
13125 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13126 item->defValue, 0, 1, 1, 0);
13127 if (ret == 0) {
13128 /*
13129 * Store the computed value.
13130 */
13131 item->defVal = ctxt->vctxt->value;
13132 ctxt->vctxt->value = NULL;
13133 } else if (ret > 0) {
13134 if (ctxt != NULL) {
13135 xmlSchemaPSimpleTypeErr(ctxt,
13136 XML_SCHEMAP_A_PROPS_CORRECT_2,
13137 NULL, NULL, node,
13138 type, NULL, item->defValue,
13139 NULL, NULL, NULL);
13140 }
13141 } else if (ret < 0) {
13142 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13143 NULL, NULL, node,
13144 "Internal error: xmlSchemaAttrCheckValConstr, "
13145 "failed to validate the value constraint of the "
13146 "attribute decl/use against the type '%s'",
13147 type->name);
13148 }
13149 }
13150}
13151
13152#if 0 /* Not used yet. */
13153static int
13154xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13155 xmlSchemaElementPtr edecl)
13156{
13157 /*
13158 * TODO: 1 The values of the properties of an element declaration must be as
13159 * described in the property tableau in The Element Declaration Schema
13160 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13161 */
13162 /*
13163 * 2 If there is a {value constraint}, the canonical lexical
13164 * representation of its value must be ·valid· with respect to the {type
13165 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13166 *
13167 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13168 */
13169 /*
13170 * 3 If there is a non-·absent· {substitution group affiliation},
13171 * then {scope} must be global.
13172 *
13173 * NOTE: This is done in xmlSchemaParseElement.
13174 * TODO: Move it to this layer here.
13175 */
13176 /*
13177 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13178 * of the element declaration must be validly derived from the {type
13179 * definition} of the {substitution group affiliation}, given the value
13180 * of the {substitution group exclusions} of the {substitution group
13181 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13182 * (if the {type definition} is complex) or as defined in
13183 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13184 * simple).
13185 */
13186 /*
13187 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13188 * is or is derived from ID then there must not be a {value constraint}.
13189 * Note: The use of ID as a type definition for elements goes beyond
13190 * XML 1.0, and should be avoided if backwards compatibility is desired
13191 */
13192 /*
13193 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13194 * be possible to return to an element declaration by repeatedly following
13195 * the {substitution group affiliation} property.
13196 */
13197}
13198#endif
13199
13200/**
13201 * xmlSchemaCheckElemValConstr:
13202 * @item: an schema element declaration/particle
13203 * @ctxt: a schema parser context
13204 * @name: the name of the attribute
13205 *
13206 * Validates the value constraints of an element declaration.
13207 *
13208 * Fixes finish doing the computations on the element declarations.
13209 */
13210static void
13211xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13212 xmlSchemaParserCtxtPtr ctxt,
13213 const xmlChar * name ATTRIBUTE_UNUSED)
13214{
13215 if (decl->value != NULL) {
13216 int ret;
13217 xmlNodePtr node = NULL;
13218 xmlSchemaTypePtr type;
13219
13220 /*
13221 * 2 If there is a {value constraint}, the canonical lexical
13222 * representation of its value must be ·valid· with respect to the {type
13223 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13224 */
13225 if (decl->subtypes == NULL) {
13226 xmlSchemaPErr(ctxt, decl->node,
13227 XML_SCHEMAP_INTERNAL,
13228 "Internal error: xmlSchemaCheckElemValConstr, "
13229 "type is missing... skipping validation of "
13230 "the value constraint", NULL, NULL);
13231 return;
13232 }
13233 /*
13234 * Ensure there's a validation context.
13235 */
13236 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13237 return;
13238
13239 type = decl->subtypes;
13240
13241 if (decl->node != NULL) {
13242 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13243 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13244 else
13245 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13246 }
13247 ctxt->vctxt->node = node;
13248 ctxt->vctxt->cur = NULL;
13249 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13250 node);
13251 if (ret == 0) {
13252 /*
13253 * Consume the computed value.
13254 */
13255 decl->defVal = ctxt->vctxt->value;
13256 ctxt->vctxt->value = NULL;
13257 } else if (ret < 0) {
13258 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13259 NULL, NULL, node,
13260 "Internal error: xmlSchemaElemCheckValConstr, "
13261 "failed to validate the value constraint of the "
13262 "element declaration '%s'",
13263 decl->name);
13264 }
13265 }
13266}
13267
13268/**
13269 * xmlSchemaAttrFixup:
13270 * @item: an schema attribute declaration/use.
13271 * @ctxt: a schema parser context
13272 * @name: the name of the attribute
13273 *
13274 * Fixes finish doing the computations on attribute declarations/uses.
13275 */
13276static void
13277xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13278 xmlSchemaParserCtxtPtr ctxt,
13279 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013280{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013281 /*
13282 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013283 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013284 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013285 /*
13286 * The simple type definition corresponding to the <simpleType> element
13287 * information item in the [children], if present, otherwise the simple
13288 * type definition ·resolved· to by the ·actual value· of the type
13289 * [attribute], if present, otherwise the ·simple ur-type definition·.
13290 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013291 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013292 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013293 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13294 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013295 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013296 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013297 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013298
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013299 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13300 item->typeNs);
13301 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013302 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013303 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013304 NULL, (xmlSchemaTypePtr) item, item->node,
13305 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013306 XML_SCHEMA_TYPE_SIMPLE, NULL);
13307 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013308 item->subtypes = type;
13309
13310 } else if (item->ref != NULL) {
13311 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013312
Daniel Veillardc0826a72004-08-10 14:17:33 +000013313 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013314 * We have an attribute use here; assign the referenced
13315 * attribute declaration.
13316 */
13317 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013318 * TODO: Evaluate, what errors could occur if the declaration is not
13319 * found. It might be possible that the "typefixup" might crash if
13320 * no ref declaration was found.
13321 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013322 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13323 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013324 xmlSchemaPResCompAttrErr(ctxt,
13325 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013326 NULL, (xmlSchemaTypePtr) item, item->node,
13327 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013328 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013329 return;
13330 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013331 item->refDecl = decl;
13332 xmlSchemaAttrFixup(decl, ctxt, NULL);
13333
13334 item->subtypes = decl->subtypes;
13335 /*
13336 * Attribute Use Correct
13337 * au-props-correct.2: If the {attribute declaration} has a fixed
13338 * {value constraint}, then if the attribute use itself has a
13339 * {value constraint}, it must also be fixed and its value must match
13340 * that of the {attribute declaration}'s {value constraint}.
13341 */
13342 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13343 (item->defValue != NULL)) {
13344 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13345 (!xmlStrEqual(item->defValue, decl->defValue))) {
13346 xmlSchemaPCustomErr(ctxt,
13347 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13348 NULL, NULL, item->node,
13349 "The value constraint must be fixed "
13350 "and match the referenced attribute "
13351 "declarations's value constraint '%s'",
13352 decl->defValue);
13353 }
13354 /*
13355 * FUTURE: One should change the values of the attr. use
13356 * if ever validation should be attempted even if the
13357 * schema itself was not fully valid.
13358 */
13359 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013360 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013361 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13362 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013363}
13364
13365/**
13366 * xmlSchemaParse:
13367 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013368 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013369 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013370 * XML Shema struture which can be used to validate instances.
13371 * *WARNING* this interface is highly subject to change
13372 *
13373 * Returns the internal XML Schema structure built from the resource or
13374 * NULL in case of error
13375 */
13376xmlSchemaPtr
13377xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13378{
13379 xmlSchemaPtr ret = NULL;
13380 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013381 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013382 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013383
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013384 /*
13385 * This one is used if the schema to be parsed was specified via
13386 * the API; i.e. not automatically by the validated instance document.
13387 */
13388
Daniel Veillard4255d502002-04-16 15:50:10 +000013389 xmlSchemaInitTypes();
13390
Daniel Veillard6045c902002-10-09 21:13:59 +000013391 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013392 return (NULL);
13393
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013394 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013395 ctxt->counter = 0;
13396 ctxt->container = NULL;
13397
13398 /*
13399 * First step is to parse the input document into an DOM/Infoset
13400 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013401 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013402 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13403 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013404 if (doc == NULL) {
13405 xmlSchemaPErr(ctxt, NULL,
13406 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013407 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013408 ctxt->URL, NULL);
13409 return (NULL);
13410 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013411 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013412 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13413 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013414 if (doc == NULL) {
13415 xmlSchemaPErr(ctxt, NULL,
13416 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013417 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013418 NULL, NULL);
13419 return (NULL);
13420 }
13421 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013422 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013423 } else if (ctxt->doc != NULL) {
13424 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013425 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013426 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013427 xmlSchemaPErr(ctxt, NULL,
13428 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013429 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013430 NULL, NULL);
13431 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013432 }
13433
13434 /*
13435 * Then extract the root and Schema parse it
13436 */
13437 root = xmlDocGetRootElement(doc);
13438 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013439 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13440 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013441 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013442 if (!preserve) {
13443 xmlFreeDoc(doc);
13444 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013445 return (NULL);
13446 }
13447
13448 /*
13449 * Remove all the blank text nodes
13450 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013451 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013452
13453 /*
13454 * Then do the parsing for good
13455 */
13456 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013457 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013458 if (!preserve) {
13459 xmlFreeDoc(doc);
13460 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013461 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013462 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013463 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013464 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013465 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013466 ctxt->ctxtType = NULL;
13467 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013468 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013469 * Then fixup all attributes declarations
13470 */
13471 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13472
13473 /*
13474 * Then fixup all attributes group declarations
13475 */
13476 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13477 ctxt);
13478
13479 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013480 * Check attribute groups for circular references.
13481 */
13482 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13483 xmlSchemaCheckAttributeGroupCircular, ctxt);
13484
13485 /*
13486 * Then fixup all model group definitions.
13487 */
13488 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013489
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013490 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013491 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013492 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013493 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013494
13495 /*
13496 * Then fix references of element declaration; apply constraints.
13497 */
13498 xmlHashScanFull(ret->elemDecl,
13499 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013500
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013501 /*
13502 * Check model groups defnitions for circular references.
13503 */
13504 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13505 xmlSchemaCheckGroupDefCircular, ctxt);
13506
Daniel Veillard4255d502002-04-16 15:50:10 +000013507 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013508 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013509 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013510 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013511 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013512
13513 /*
13514 * Then check the defaults part of the type like facets values
13515 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013516 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
13517 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013518
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013519 /*
13520 * Validate the value constraint of attribute declarations/uses.
13521 */
13522 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13523
13524 /*
13525 * Validate the value constraint of element declarations.
13526 */
13527 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13528
Daniel Veillardc0826a72004-08-10 14:17:33 +000013529
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013530 if (ctxt->nberrors != 0) {
13531 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013532 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013533 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013534 return (ret);
13535}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013536
Daniel Veillard4255d502002-04-16 15:50:10 +000013537/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013538 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013539 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013540 * @err: the error callback
13541 * @warn: the warning callback
13542 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013543 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013544 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013545 */
13546void
13547xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013548 xmlSchemaValidityErrorFunc err,
13549 xmlSchemaValidityWarningFunc warn, void *ctx)
13550{
Daniel Veillard4255d502002-04-16 15:50:10 +000013551 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013552 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013553 ctxt->error = err;
13554 ctxt->warning = warn;
13555 ctxt->userData = ctx;
13556}
13557
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013558/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013559 * xmlSchemaGetParserErrors:
13560 * @ctxt: a XMl-Schema parser context
13561 * @err: the error callback result
13562 * @warn: the warning callback result
13563 * @ctx: contextual data for the callbacks result
13564 *
13565 * Get the callback information used to handle errors for a parser context
13566 *
13567 * Returns -1 in case of failure, 0 otherwise
13568 */
13569int
13570xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13571 xmlSchemaValidityErrorFunc * err,
13572 xmlSchemaValidityWarningFunc * warn, void **ctx)
13573{
13574 if (ctxt == NULL)
13575 return(-1);
13576 if (err != NULL)
13577 *err = ctxt->error;
13578 if (warn != NULL)
13579 *warn = ctxt->warning;
13580 if (ctx != NULL)
13581 *ctx = ctxt->userData;
13582 return(0);
13583}
13584
13585/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013586 * xmlSchemaFacetTypeToString:
13587 * @type: the facet type
13588 *
13589 * Convert the xmlSchemaTypeType to a char string.
13590 *
13591 * Returns the char string representation of the facet type if the
13592 * type is a facet and an "Internal Error" string otherwise.
13593 */
13594static const char *
13595xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13596{
13597 switch (type) {
13598 case XML_SCHEMA_FACET_PATTERN:
13599 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013600 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013601 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013602 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013603 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013604 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013605 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013606 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013607 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013608 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013609 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013610 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013611 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013612 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013613 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013614 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013615 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013616 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013617 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013618 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013619 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013620 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013621 return ("fractionDigits");
13622 default:
13623 break;
13624 }
13625 return ("Internal Error");
13626}
13627
Daniel Veillardc0826a72004-08-10 14:17:33 +000013628static xmlChar *
13629xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
13630 const xmlChar *cur = value;
13631 xmlChar *ret = NULL, *mcur;
13632
13633 if (value == NULL)
13634 return(NULL);
13635
13636 while ((*cur != 0) &&
13637 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
13638 cur++;
13639 }
13640 if (*cur == 0)
13641 return (NULL);
13642 ret = xmlStrdup(value);
13643 /* TODO FIXME: I guess gcc will bark at this. */
13644 mcur = (xmlChar *) (ret + (cur - value));
13645 do {
13646 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
13647 *mcur = ' ';
13648 mcur++;
13649 } while (*mcur != 0);
13650 return(ret);
13651}
13652
13653static int
13654xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13655{
13656 xmlSchemaTypePtr anc;
13657
13658 /*
13659 * The normalization type can be changed only for types which are derived
13660 * from xsd:string.
13661 */
13662 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13663 if ((type->builtInType == XML_SCHEMAS_STRING) &&
13664 (type->builtInType == XML_SCHEMAS_NORMSTRING))
13665
13666 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13667 else {
13668 /*
13669 * For all ·atomic· datatypes other than string (and types ·derived·
13670 * by ·restriction· from it) the value of whiteSpace is fixed to
13671 * collapse
13672 */
13673 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13674 }
13675 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13676 /*
13677 * For list types the facet "whiteSpace" is fixed to "collapse".
13678 */
13679 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13680 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13681 return (-1);
13682 } else if (type->facetSet != NULL) {
13683 xmlSchemaTypePtr anyST;
13684 xmlSchemaFacetLinkPtr lin;
13685
13686 /*
13687 * Atomic types.
13688 */
13689 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13690 anc = type->baseType;
13691 do {
13692 /*
13693 * For all ·atomic· datatypes other than string (and types ·derived·
13694 * by ·restriction· from it) the value of whiteSpace is fixed to
13695 * collapse
13696 */
13697 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13698 (anc->builtInType == XML_SCHEMAS_STRING)) {
13699
13700 lin = type->facetSet;
13701 do {
13702 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13703 if (lin->facet->whitespace ==
13704 XML_SCHEMAS_FACET_COLLAPSE) {
13705 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13706 } else if (lin->facet->whitespace ==
13707 XML_SCHEMAS_FACET_REPLACE) {
13708 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13709 } else
13710 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13711 break;
13712 }
13713 lin = lin->next;
13714 } while (lin != NULL);
13715 break;
13716 }
13717 anc = anc->baseType;
13718 } while (anc != anyST);
13719 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13720 }
13721 return (-1);
13722}
13723
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013724/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013725 * xmlSchemaValidateFacetsInternal:
13726 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013727 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013728 * @facets: the list of facets to check
13729 * @value: the lexical repr of the value to validate
13730 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013731 * @fireErrors: if 0, only internal errors will be fired;
13732 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013733 *
13734 * Check a value against all facet conditions
13735 *
13736 * Returns 0 if the element is schemas valid, a positive error code
13737 * number otherwise and -1 in case of internal or API error.
13738 */
13739static int
13740xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013741 xmlSchemaTypePtr type,
13742 const xmlChar * value,
13743 unsigned long length,
13744 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013745{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013746 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013747 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013748 xmlSchemaTypePtr biType; /* The build-in type. */
13749 xmlSchemaTypePtr tmpType;
13750 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013751 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013752 xmlSchemaFacetPtr facet;
13753 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013754
Daniel Veillardc0826a72004-08-10 14:17:33 +000013755#ifdef DEBUG_UNION_VALIDATION
13756 printf("Facets of type: '%s'\n", (const char *) type->name);
13757 printf(" fireErrors: %d\n", fireErrors);
13758#endif
13759
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013760 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013761 /*
13762 * NOTE: Do not jump away, if the facetSet of the given type is
13763 * empty: until now, "pattern" facets of the *base types* need to
13764 * be checked as well.
13765 */
13766 biType = type->baseType;
13767 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13768 biType = biType->baseType;
13769 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013770 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013771 "Internal error: xmlSchemaValidateFacetsInternal, "
13772 "the base type axis of the given type '%s' does not resolve to "
13773 "a built-in type.\n",
13774 type->name, NULL);
13775 return (-1);
13776 }
13777
13778 if (type->facetSet != NULL) {
13779 facetLink = type->facetSet;
13780 while (facetLink != NULL) {
13781 facet = facetLink->facet;
13782 /*
13783 * Skip the pattern "whiteSpace": it is used to
13784 * format the character content beforehand.
13785 */
13786 switch (facet->type) {
13787 case XML_SCHEMA_FACET_WHITESPACE:
13788 case XML_SCHEMA_FACET_PATTERN:
13789 case XML_SCHEMA_FACET_ENUMERATION:
13790 break;
13791 case XML_SCHEMA_FACET_LENGTH:
13792 case XML_SCHEMA_FACET_MINLENGTH:
13793 case XML_SCHEMA_FACET_MAXLENGTH:
13794 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13795 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13796 value, length, 0);
13797 len = length;
13798 } else
13799 ret = xmlSchemaValidateLengthFacet(biType, facet,
13800 value, ctxt->value, &len);
13801 break;
13802 default:
13803 ret = xmlSchemaValidateFacet(biType, facet, value,
13804 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013805 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013806 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013807 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 "Internal error: xmlSchemaValidateFacetsInternal, "
13809 "validating facet of type '%s'.\n",
13810 type->name, NULL);
13811 break;
13812 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013813 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013814 type, facet, NULL, NULL, NULL, NULL);
13815 }
13816
13817 facetLink = facetLink->next;
13818 }
13819 if (ret >= 0) {
13820 /*
13821 * Process enumerations.
13822 */
13823 retFacet = 0;
13824 facetLink = type->facetSet;
13825 while (facetLink != NULL) {
13826 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
13827 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13828 value, ctxt->value);
13829 if (retFacet <= 0)
13830 break;
13831 }
13832 facetLink = facetLink->next;
13833 }
13834 if (retFacet > 0) {
13835 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
13836 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013837 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013838 value, 0, type, NULL, NULL, NULL, NULL, NULL);
13839 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013840 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013841 "Internal error: xmlSchemaValidateFacetsInternal, "
13842 "validating facet of type '%s'.\n",
13843 BAD_CAST "enumeration", NULL);
13844 ret = -1;
13845 }
13846 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013847 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013848 if (ret >= 0) {
13849 /*
13850 * Process patters. Pattern facets are ORed at type level
13851 * and ANDed if derived. Walk the base type axis.
13852 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013853 tmpType = type;
13854 facet = NULL;
13855 do {
13856 retFacet = 0;
13857 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013858 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013859 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13860 continue;
13861 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13862 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013863 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013864 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013865 else if (retFacet < 0) {
13866 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13867 "Internal error: xmlSchemaValidateFacetsInternal, "
13868 "validating 'pattern' facet '%s' of type '%s'.\n",
13869 facetLink->facet->value, tmpType->name);
13870 ret = -1;
13871 break;
13872 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013873 /* Save the last non-validating facet. */
13874 facet = facetLink->facet;
13875 }
13876 if (retFacet != 0)
13877 break;
13878 tmpType = tmpType->baseType;
13879 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013880 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013881 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13882 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013883 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013884 NULL, NULL, NULL, NULL);
13885 }
13886 }
13887 }
13888
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013889 return (ret);
13890}
13891
Daniel Veillard4255d502002-04-16 15:50:10 +000013892/************************************************************************
13893 * *
13894 * Simple type validation *
13895 * *
13896 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013897
Daniel Veillard4255d502002-04-16 15:50:10 +000013898
13899/************************************************************************
13900 * *
13901 * DOM Validation code *
13902 * *
13903 ************************************************************************/
13904
Daniel Veillard4255d502002-04-16 15:50:10 +000013905static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013906 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013907 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013908static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013909 xmlSchemaTypePtr type,
13910 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000013911
Daniel Veillard3646d642004-06-02 19:19:14 +000013912
13913/**
13914 * xmlSchemaFreeAttrStates:
13915 * @state: a list of attribute states
13916 *
13917 * Free the given list of attribute states
13918 *
13919 */
13920static void
13921xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13922{
13923 xmlSchemaAttrStatePtr tmp;
13924 while (state != NULL) {
13925 tmp = state;
13926 state = state->next;
13927 xmlFree(tmp);
13928 }
13929}
13930
Daniel Veillard4255d502002-04-16 15:50:10 +000013931/**
13932 * xmlSchemaRegisterAttributes:
13933 * @ctxt: a schema validation context
13934 * @attrs: a list of attributes
13935 *
13936 * Register the list of attributes as the set to be validated on that element
13937 *
13938 * Returns -1 in case of error, 0 otherwise
13939 */
13940static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013941xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
13942{
Daniel Veillard3646d642004-06-02 19:19:14 +000013943 xmlSchemaAttrStatePtr tmp;
13944
13945 ctxt->attr = NULL;
13946 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013947 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013948 if ((attrs->ns != NULL) &&
13949 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
13950 attrs = attrs->next;
13951 continue;
13952 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013953 tmp = (xmlSchemaAttrStatePtr)
13954 xmlMalloc(sizeof(xmlSchemaAttrState));
13955 if (tmp == NULL) {
13956 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
13957 return (-1);
13958 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013959 tmp->attr = attrs;
13960 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
13961 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013962 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013963 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013964 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013965 else
13966 ctxt->attrTop->next = tmp;
13967 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013968 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013969 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013970 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000013971}
13972
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013973#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000013974/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013975 * xmlSchemaValidateCheckNodeList
13976 * @nodelist: the list of nodes
13977 *
13978 * Check the node list is only made of text nodes and entities pointing
13979 * to text nodes
13980 *
13981 * Returns 1 if true, 0 if false and -1 in case of error
13982 */
13983static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013984xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
13985{
Daniel Veillard4255d502002-04-16 15:50:10 +000013986 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013987 if (nodelist->type == XML_ENTITY_REF_NODE) {
13988 TODO /* implement recursion in the entity content */
13989 }
13990 if ((nodelist->type != XML_TEXT_NODE) &&
13991 (nodelist->type != XML_COMMENT_NODE) &&
13992 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000013993 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013994 return (0);
13995 }
13996 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013997 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013998 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013999}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014000#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014001
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014002static void
14003xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14004{
14005 int i, nbItems;
14006 xmlSchemaTypePtr item, *items;
14007
14008
14009 /*
14010 * During the Assemble of the schema ctxt->curItems has
14011 * been filled with the relevant new items. Fix those up.
14012 */
14013 nbItems = ctxt->assemble->nbItems;
14014 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14015
14016 for (i = 0; i < nbItems; i++) {
14017 item = items[i];
14018 switch (item->type) {
14019 case XML_SCHEMA_TYPE_ATTRIBUTE:
14020 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14021 break;
14022 case XML_SCHEMA_TYPE_ELEMENT:
14023 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14024 NULL, NULL, NULL);
14025 break;
14026 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14027 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14028 ctxt, NULL);
14029 break;
14030 case XML_SCHEMA_TYPE_GROUP:
14031 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14032 default:
14033 break;
14034 }
14035 }
14036 /*
14037 * Circularity checks.
14038 */
14039 for (i = 0; i < nbItems; i++) {
14040 item = items[i];
14041 switch (item->type) {
14042 case XML_SCHEMA_TYPE_GROUP:
14043 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14044 break;
14045 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14046 xmlSchemaCheckAttributeGroupCircular(
14047 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14048 break;
14049 default:
14050 break;
14051 }
14052 }
14053 /*
14054 * Fixup for all other item.
14055 * TODO: Hmm, not sure if starting from complex/simple types,
14056 * all subsequent items will be reached.
14057 */
14058 for (i = 0; i < nbItems; i++) {
14059 item = items[i];
14060 switch (item->type) {
14061 case XML_SCHEMA_TYPE_SIMPLE:
14062 case XML_SCHEMA_TYPE_COMPLEX:
14063 xmlSchemaTypeFixup(item, ctxt, NULL);
14064 break;
14065 default:
14066 break;
14067 }
14068 }
14069 /*
14070 * Check facet values. Note that facets are
14071 * hold by complex and simple type components only.
14072 */
14073 for (i = 0; i < nbItems; i++) {
14074 item = items[i];
14075 switch (item->type) {
14076 case XML_SCHEMA_TYPE_SIMPLE:
14077 case XML_SCHEMA_TYPE_COMPLEX:
14078 xmlSchemaCheckDefaults(item, ctxt, NULL);
14079 break;
14080 default:
14081 break;
14082 }
14083 }
14084 /*
14085 * Build the content model for complex types.
14086 */
14087 for (i = 0; i < nbItems; i++) {
14088 item = items[i];
14089 switch (item->type) {
14090 case XML_SCHEMA_TYPE_COMPLEX:
14091 xmlSchemaBuildContentModel(item, ctxt, NULL);
14092 break;
14093 default:
14094 break;
14095 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014096 }
14097 /*
14098 * Validate value contraint values.
14099 */
14100 for (i = 0; i < nbItems; i++) {
14101 item = items[i];
14102 switch (item->type) {
14103 case XML_SCHEMA_TYPE_ATTRIBUTE:
14104 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14105 break;
14106 case XML_SCHEMA_TYPE_ELEMENT:
14107 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14108 break;
14109 default:
14110 break;
14111 }
14112 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014113}
14114
14115/**
14116 * xmlSchemaAssembleByLocation:
14117 * @pctxt: a schema parser context
14118 * @vctxt: a schema validation context
14119 * @schema: the existing schema
14120 * @node: the node that fired the assembling
14121 * @nsName: the namespace name of the new schema
14122 * @location: the location of the schema
14123 *
14124 * Expands an existing schema by an additional schema.
14125 *
14126 * Returns 0 if the new schema is correct, a positive error code
14127 * number otherwise and -1 in case of an internal or API error.
14128 */
14129static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014130xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14131 xmlSchemaPtr schema,
14132 xmlNodePtr node,
14133 const xmlChar *nsName,
14134 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014135{
14136 const xmlChar *targetNs, *oldtns;
14137 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014138 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014139 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014140 xmlSchemaParserCtxtPtr pctxt;
14141
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014142 /*
14143 * This should be used:
14144 * 1. on <import>(s)
14145 * 2. if requested by the validated instance
14146 * 3. if requested via the API
14147 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014148 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014149 return (-1);
14150 /*
14151 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014152 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014153 if ((vctxt->pctxt == NULL) &&
14154 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14155 xmlSchemaVErr(vctxt, node,
14156 XML_SCHEMAV_INTERNAL,
14157 "Internal error: xmlSchemaAssembleByLocation, "
14158 "failed to create a temp. parser context.\n",
14159 NULL, NULL);
14160 return (-1);
14161 }
14162 pctxt = vctxt->pctxt;
14163 /*
14164 * Set the counter to produce unique names for anonymous items.
14165 */
14166 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014167 /*
14168 * Acquire the schema document.
14169 */
14170 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14171 nsName, location, &doc, &targetNs, 0);
14172 if (ret != 0) {
14173 if (doc != NULL)
14174 xmlFreeDoc(doc);
14175 } else if (doc != NULL) {
14176 docElem = xmlDocGetRootElement(doc);
14177 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014178 * Create new assemble info.
14179 */
14180 if (pctxt->assemble == NULL) {
14181 pctxt->assemble = xmlSchemaNewAssemble();
14182 if (pctxt->assemble == NULL) {
14183 xmlSchemaVErrMemory(vctxt,
14184 "Memory error: xmlSchemaAssembleByLocation, "
14185 "allocating assemble info", NULL);
14186 xmlFreeDoc(doc);
14187 return (-1);
14188 }
14189 }
14190 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014191 * Save and reset the context & schema.
14192 */
14193 oldflags = schema->flags;
14194 oldtns = schema->targetNamespace;
14195 olddoc = schema->doc;
14196
14197 xmlSchemaClearSchemaDefaults(schema);
14198 schema->targetNamespace = targetNs;
14199 /* schema->nbCurItems = 0; */
14200 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014201 pctxt->ctxtType = NULL;
14202 pctxt->parentItem = NULL;
14203
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014204 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14205 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014206 xmlSchemaPostSchemaAssembleFixup(pctxt);
14207 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014208 * Set the counter of items.
14209 */
14210 schema->counter = pctxt->counter;
14211 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014212 * Free the list of assembled components.
14213 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014214 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014215 /*
14216 * Restore the context & schema.
14217 */
14218 schema->flags = oldflags;
14219 schema->targetNamespace = oldtns;
14220 schema->doc = olddoc;
14221 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014222 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014223 return (ret);
14224}
14225
14226/**
14227 * xmlSchemaAssembleByXSIAttr:
14228 * @vctxt: a schema validation context
14229 * @xsiAttr: an xsi attribute
14230 * @noNamespace: whether a schema with no target namespace is exptected
14231 *
14232 * Expands an existing schema by an additional schema using
14233 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14234 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14235 * must be set to 1.
14236 *
14237 * Returns 0 if the new schema is correct, a positive error code
14238 * number otherwise and -1 in case of an internal or API error.
14239 */
14240static int
14241xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14242 xmlAttrPtr xsiAttr,
14243 int noNamespace)
14244{
14245 xmlChar *value;
14246 const xmlChar *cur, *end;
14247 const xmlChar *nsname = NULL, *location;
14248 int count = 0;
14249 int ret = 0;
14250
14251 if (xsiAttr == NULL) {
14252 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14253 NULL, NULL,
14254 "Internal error: xmlSchemaAssembleByXSIAttr, "
14255 "bad arguments", NULL);
14256 return (-1);
14257 }
14258 /*
14259 * Parse the value; we will assume an even number of values
14260 * to be given (this is how Xerces and XSV work).
14261 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014262 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014263 cur = value;
14264 do {
14265 if (noNamespace != 1) {
14266 /*
14267 * Get the namespace name.
14268 */
14269 while (IS_BLANK_CH(*cur))
14270 cur++;
14271 end = cur;
14272 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14273 end++;
14274 if (end == cur)
14275 break;
14276 count++;
14277 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14278 cur = end;
14279 }
14280 /*
14281 * Get the URI.
14282 */
14283 while (IS_BLANK_CH(*cur))
14284 cur++;
14285 end = cur;
14286 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14287 end++;
14288 if (end == cur)
14289 break;
14290 count++;
14291 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014292 cur = end;
14293 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014294 xsiAttr->parent, nsname, location);
14295 if (ret == -1) {
14296 xmlSchemaVCustomErr(vctxt,
14297 XML_SCHEMAV_INTERNAL,
14298 (xmlNodePtr) xsiAttr, NULL,
14299 "Internal error: xmlSchemaAssembleByXSIAttr, "
14300 "assembling schemata", NULL);
14301 if (value != NULL)
14302 xmlFree(value);
14303 return (-1);
14304 }
14305 } while (*cur != 0);
14306 if (value != NULL)
14307 xmlFree(value);
14308 return (ret);
14309}
14310
14311/**
14312 * xmlSchemaAssembleByXSIElem:
14313 * @vctxt: a schema validation context
14314 * @elem: an element node possibly holding xsi attributes
14315 * @noNamespace: whether a schema with no target namespace is exptected
14316 *
14317 * Assembles an existing schema by an additional schema using
14318 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14319 * of the given @elem.
14320 *
14321 * Returns 0 if the new schema is correct, a positive error code
14322 * number otherwise and -1 in case of an internal or API error.
14323 */
14324static int
14325xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14326 xmlNodePtr elem)
14327{
14328 int ret = 0, retNs = 0;
14329 xmlAttrPtr attr;
14330
14331 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14332 if (attr != NULL) {
14333 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14334 if (retNs == -1)
14335 return (-1);
14336 }
14337 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14338 if (attr != NULL) {
14339 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14340 if (ret == -1)
14341 return (-1);
14342 }
14343 if (retNs != 0)
14344 return (retNs);
14345 else
14346 return (ret);
14347}
14348
Daniel Veillard4255d502002-04-16 15:50:10 +000014349/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014350 * xmlSchemaValidateCallback:
14351 * @ctxt: a schema validation context
14352 * @name: the name of the element detected (might be NULL)
14353 * @type: the type
14354 *
14355 * A transition has been made in the automata associated to an element
14356 * content model
14357 */
14358static void
14359xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014360 const xmlChar * name ATTRIBUTE_UNUSED,
14361 xmlSchemaTypePtr type, xmlNodePtr node)
14362{
Daniel Veillard4255d502002-04-16 15:50:10 +000014363 xmlSchemaTypePtr oldtype = ctxt->type;
14364 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014365
Daniel Veillard4255d502002-04-16 15:50:10 +000014366#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014367 xmlGenericError(xmlGenericErrorContext,
14368 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014369 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014370#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014371 /*
14372 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14373 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014374 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014375 ctxt->node = node;
14376 ctxt->cur = node->children;
14377 /*
14378 * Assemble new schemata using xsi.
14379 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014380 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014381 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014382
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014383 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14384 if (ret == -1) {
14385 xmlSchemaVCustomErr(ctxt,
14386 XML_SCHEMAV_INTERNAL,
14387 ctxt->node, NULL,
14388 "Internal error: xmlSchemaValidateElement, "
14389 "assembling schema by xsi", NULL);
14390 return;
14391 }
14392 /*
14393 * NOTE: We won't react on schema parser errors here.
14394 * TODO: But a warning would be nice.
14395 */
14396 }
14397 switch (type->type) {
14398 case XML_SCHEMA_TYPE_ELEMENT: {
14399 /*
14400 * NOTE: The build of the content model
14401 * (xmlSchemaBuildAContentModel) ensures that the element
14402 * declaration (and not a reference to it) will be given.
14403 */
14404 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14405 /*
14406 * This is paranoid coding ;-)... it should not
14407 * happen here any more.
14408 */
14409 xmlSchemaVCustomErr(ctxt,
14410 XML_SCHEMAV_INTERNAL,
14411 node, NULL,
14412 "Internal error: xmlSchemaValidateCallback, "
14413 "element declaration 'reference' encountered, "
14414 "but an element declaration was expected",
14415 NULL);
14416 return;
14417 }
14418 xmlSchemaValidateElementByDeclaration(ctxt,
14419 (xmlSchemaElementPtr) type);
14420 break;
14421 }
14422 case XML_SCHEMA_TYPE_ANY:
14423 xmlSchemaValidateElementByWildcard(ctxt, type);
14424 break;
14425 default:
14426 break;
14427 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014428 ctxt->type = oldtype;
14429 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014430}
Daniel Veillard4255d502002-04-16 15:50:10 +000014431
Daniel Veillard01fa6152004-06-29 17:04:39 +000014432/**
14433 * xmlSchemaValidateSimpleTypeValue:
14434 * @ctxt: a schema validation context
14435 * @value: the value to be validated
14436 * @fireErrors: shall errors be reported?
14437 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014438 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014439 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014440 *
14441 * Validates a value by the given type (user derived or built-in).
14442 *
14443 * Returns 0 if the value is valid, a positive error code
14444 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014445 */
14446static int
14447xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014448 xmlSchemaTypePtr type,
14449 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014450 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014451 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014452 int normalize,
14453 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014454{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014455 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014456 int ret = 0;
14457 xmlChar *normValue = NULL;
14458 int wtsp;
14459
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014460 node = ctxt->node;
14461 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014462 wtsp = ctxt->valueWS;
14463 /*
14464 * Normalize the value.
14465 */
14466 if (normalize &&
14467 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14468 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14469
14470 if ((norm != -1) && (norm > ctxt->valueWS)) {
14471 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14472 normValue = xmlSchemaCollapseString(value);
14473 else
14474 normValue = xmlSchemaWhiteSpaceReplace(value);
14475 ctxt->valueWS = norm;
14476 if (normValue != NULL)
14477 value = (const xmlChar *) normValue;
14478 }
14479 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014480 /*
14481 * The nodes of a content must be checked only once,
14482 * this is not working since list types will fire this
14483 * multiple times.
14484 */
14485 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14486 xmlNodePtr cur = ctxt->cur;
14487
14488 do {
14489 switch (cur->type) {
14490 case XML_TEXT_NODE:
14491 case XML_CDATA_SECTION_NODE:
14492 case XML_PI_NODE:
14493 case XML_COMMENT_NODE:
14494 case XML_XINCLUDE_START:
14495 case XML_XINCLUDE_END:
14496 break;
14497 case XML_ENTITY_REF_NODE:
14498 case XML_ENTITY_NODE:
14499 /* TODO: Scour the entities for illegal nodes. */
14500 TODO break;
14501 case XML_ELEMENT_NODE: {
14502 /* NOTE: Changed to an internal error, since the
14503 * existence of an element node will be already checked in
14504 * xmlSchemaValidateElementBySimpleType and in
14505 * xmlSchemaValidateElementByComplexType.
14506 */
14507 xmlSchemaVCustomErr(ctxt,
14508 XML_SCHEMAV_INTERNAL,
14509 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14510 node, type,
14511 "Element '%s' found in simple type content",
14512 cur->name);
14513 return (XML_SCHEMAV_INTERNAL);
14514 }
14515 case XML_ATTRIBUTE_NODE:
14516 case XML_DOCUMENT_NODE:
14517 case XML_DOCUMENT_TYPE_NODE:
14518 case XML_DOCUMENT_FRAG_NODE:
14519 case XML_NOTATION_NODE:
14520 case XML_HTML_DOCUMENT_NODE:
14521 case XML_DTD_NODE:
14522 case XML_ELEMENT_DECL:
14523 case XML_ATTRIBUTE_DECL:
14524 case XML_ENTITY_DECL:
14525 case XML_NAMESPACE_DECL:
14526#ifdef LIBXML_DOCB_ENABLED
14527 case XML_DOCB_DOCUMENT_NODE:
14528#endif
14529 xmlSchemaVCustomErr(ctxt,
14530 XML_SCHEMAV_INTERNAL,
14531 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14532 node, NULL,
14533 "Node of unexpected type found in simple type content",
14534 NULL);
14535 return (XML_SCHEMAV_INTERNAL);
14536 }
14537 cur = cur->next;
14538 } while (cur != NULL);
14539 }
14540
William M. Brack2f2a6632004-08-20 23:09:47 +000014541 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14542 xmlSchemaTypePtr base, anyType;
14543
14544 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14545
14546 base = type->baseType;
14547 while ((base != NULL) &&
14548 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14549 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14550 (base != anyType)) {
14551 base = base->baseType;
14552 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014553 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014554 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014555 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014556 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14557 "validating complex type '%s'\n",
14558 type->name, NULL);
14559 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14560 /*
14561 * Check facets.
14562 */
14563 /*
14564 * This is somehow not nice, since if an error occurs
14565 * the reported type will be the complex type; the spec
14566 * wants a simple type to be created on the complex type
14567 * if it has a simple content. For now we have to live with
14568 * it.
14569 */
14570 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14571 value, 0, fireErrors);
14572 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014573 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014574 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14575 "validating facets of complex type '%s'\n",
14576 type->name, NULL);
14577 } else if (ret > 0) {
14578 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014579 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014580 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014581 }
14582 }
14583 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014584
14585 if (ctxt->value != NULL) {
14586 xmlSchemaFreeValue(ctxt->value);
14587 ctxt->value = NULL;
14588 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014589 /*
14590 * STREAM-READ-CHILDREN.
14591 */
14592 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014593 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014594 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14595 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14596 else
14597 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014598 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014599 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014600 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014601 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014602 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014603 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014604 }
14605 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14606 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14607 * a literal in the ·lexical space· of {base type definition}
14608 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014609 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014610 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014611 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014612 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014613 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014614 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014615 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014616 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014617 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014618 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014619 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014620 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014621 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014622 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014623 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14624 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014625 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014626 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014627 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014628 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014629 type->name, NULL);
14630 } else if (ret > 0) {
14631 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014632 /*
14633 Disabled, since the facet validation already reports errors.
14634 if (fireErrors)
14635 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14636 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014637 }
14638 }
14639 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14640
14641 xmlSchemaTypePtr tmpType;
14642 const xmlChar *cur, *end;
14643 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014644 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014645
14646 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14647 * of white space separated tokens, each of which ·match·es a literal
14648 * in the ·lexical space· of {item type definition}
14649 */
14650
Daniel Veillardc0826a72004-08-10 14:17:33 +000014651 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014652 cur = value;
14653 do {
14654 while (IS_BLANK_CH(*cur))
14655 cur++;
14656 end = cur;
14657 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14658 end++;
14659 if (end == cur)
14660 break;
14661 tmp = xmlStrndup(cur, end - cur);
14662 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014663 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014664 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014665 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014666 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014667 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14668 "validating an item of list simple type '%s'\n",
14669 type->name, NULL);
14670 break;
14671 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014672 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014673 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014674 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014675 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014676 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014677 cur = end;
14678 } while (*cur != 0);
14679 /*
14680 * Check facets.
14681 */
14682 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014683 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014684 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014685 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014686 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014687 } else if ((ret == 0) && (applyFacets)) {
14688 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14689 value, len, fireErrors);
14690 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014691 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014692 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14693 "validating facets of list simple type '%s'\n",
14694 type->name, NULL);
14695 } else if (ret > 0) {
14696 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014697 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014698 Disabled, since the facet validation already reports errors.
14699 if (fireErrors)
14700 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014701 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014702 }
14703
Daniel Veillard01fa6152004-06-29 17:04:39 +000014704 }
14705 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14706 xmlSchemaTypeLinkPtr memberLink;
14707
14708 /*
14709 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14710 * not apply directly; however, the normalization behavior of ·union·
14711 * types is controlled by the value of whiteSpace on that one of the
14712 * ·memberTypes· against which the ·union· is successfully validated.
14713 *
14714 * This means that the value is normalized by the first validating
14715 * member type, then the facets of the union type are applied. This
14716 * needs changing of the value!
14717 */
14718
14719 /*
14720 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14721 * literal in the ·lexical space· of at least one member of
14722 * {member type definitions}
14723 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014724#ifdef DEBUG_UNION_VALIDATION
14725 printf("Union ST : '%s'\n", (const char *) type->name);
14726 printf(" fireErrors : %d\n", fireErrors);
14727 printf(" applyFacets: %d\n", applyFacets);
14728#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014729 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14730 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014731 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014732 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014733 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014734 type->name, NULL);
14735 ret = -1;
14736 }
14737 if (ret == 0) {
14738 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014739 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14740 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014741 if ((ret <= 0) || (ret == 0))
14742 break;
14743 memberLink = memberLink->next;
14744 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014745 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014746 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014747 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014748 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014749 type->name, NULL);
14750 } else if (ret > 0) {
14751 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014752 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014753 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014754 }
14755 }
14756 /*
14757 * Apply facets (pattern, enumeration).
14758 */
14759 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14760 int mws;
14761 /*
14762 * The normalization behavior of ·union· types is controlled by
14763 * the value of whiteSpace on that one of the ·memberTypes·
14764 * against which the ·union· is successfully validated.
14765 */
14766 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014767 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014768 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14769 "the value was already normalized for the union simple "
14770 "type '%s'.\n", type->name, NULL);
14771 }
14772 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14773 if (mws > ctxt->valueWS) {
14774 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14775 normValue = xmlSchemaCollapseString(value);
14776 else
14777 normValue = xmlSchemaWhiteSpaceReplace(value);
14778 if (normValue != NULL)
14779 value = (const xmlChar *) normValue;
14780 }
14781
14782 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14783 value, 0, fireErrors);
14784 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014785 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014786 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14787 "validating facets of union simple type '%s'\n",
14788 type->name, NULL);
14789 } else if (ret > 0) {
14790 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14791 /*
14792 if (fireErrors)
14793 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14794 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014795 }
14796 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014797 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014798 ctxt->valueWS = wtsp;
14799 if (normValue != NULL)
14800 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014801 return (ret);
14802}
14803
14804/**
14805 * xmlSchemaValidateSimpleTypeElement:
14806 * @ctxt: a schema validation context
14807 * @node: the element node to be validated.
14808 *
14809 * Validate the element against a simple type.
14810 *
14811 * Returns 0 if the element is valid, a positive error code
14812 * number otherwise and -1 in case of an internal or API error.
14813 */
14814static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014815xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014816 xmlSchemaTypePtr type,
14817 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014818{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014819 xmlSchemaTypePtr oldtype;
14820 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014821 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014822 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014823 int ret = 0, retval = 0;
14824
Daniel Veillard01fa6152004-06-29 17:04:39 +000014825 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014826 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
14827 "Internal error: xmlSchemaValidateElementBySimpleType, "
14828 "bad arguments", NULL);
14829 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014830 }
14831
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014832 oldtype = ctxt->type;
14833 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014834 /*
14835 * cvc-type: 3.1.2 The element information item must have no element
14836 * information item [children].
14837 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014838 /*
14839 * STREAM: Child nodes are processed.
14840 */
14841 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014842 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014843 /*
14844 * TODO: Entities, will they produce elements as well?
14845 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014846 if (cur->type == XML_ELEMENT_NODE) {
14847 xmlSchemaVCustomErr(ctxt,
14848 XML_SCHEMAV_CVC_TYPE_3_1_2,
14849 node, type,
14850 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014851 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014852 }
14853 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014854 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014855
Daniel Veillard01fa6152004-06-29 17:04:39 +000014856 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014857 * cvc-type 3.1.1:
14858 *
14859 * The attributes of must be empty, excepting those whose namespace name
14860 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
14861 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014862 */
14863 /*
14864 * STREAM: Attribute nodes are processed.
14865 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014866 attr = node->properties;
14867 while (attr != NULL) {
14868 if ((attr->ns == NULL) ||
14869 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
14870 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
14871 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
14872 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
14873 (!xmlStrEqual
14874 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014875 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014876 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
14877 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014878 }
14879 attr = attr->next;
14880 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014881 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014882 * This will skip validation if the type is 'anySimpleType' and
14883 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014884 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014885 if ((valSimpleContent == 1) &&
14886 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14887 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014888 xmlChar *value;
14889
14890 value = xmlNodeGetContent(node);
14891 /*
14892 * NOTE: This call will not check the content nodes, since
14893 * this should be checked here already.
14894 */
14895 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14896 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014897 if (value != NULL)
14898 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014899 if (retval != 0)
14900 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014901 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014902 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014903 return (ret);
14904}
Daniel Veillard4255d502002-04-16 15:50:10 +000014905
14906/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014907 * xmlSchemaValQNameAcquire:
14908 * @value: the lexical represantation of the QName value
14909 * @node: the node to search for the corresponding namespace declaration
14910 * @nsName: the resulting namespace name if found
14911 *
14912 * Checks that a value conforms to the lexical space of the type QName;
14913 * if valid, the corresponding namespace name is searched and retured
14914 * as a copy in @nsName. The local name is returned in @localName as
14915 * a copy.
14916 *
14917 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14918 * namespace declaration was found in scope; -1 in case of an internal or
14919 * API error.
14920 */
14921static int
14922xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14923 xmlChar **nsName, xmlChar **localName)
14924{
14925 int ret;
14926 xmlChar *local = NULL;
14927
14928 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14929 return (-1);
14930 *nsName = NULL;
14931 *localName = NULL;
14932 ret = xmlValidateQName(value, 1);
14933 if (ret == 0) {
14934 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014935 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014936
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014937 /*
14938 * NOTE: xmlSplitQName2 will return a duplicated
14939 * string.
14940 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014941 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014942 if (local == NULL)
14943 local = xmlStrdup(value);
14944 ns = xmlSearchNs(node->doc, node, prefix);
14945 /*
14946 * A namespace need not to be found if the prefix is NULL.
14947 */
14948 if (ns != NULL) {
14949 /*
14950 * TODO: Is it necessary to duplicate the URI here?
14951 */
14952 *nsName = xmlStrdup(ns->href);
14953 } else if (prefix != NULL) {
14954 xmlFree(prefix);
14955 if (local != NULL)
14956 xmlFree(local);
14957 return (2);
14958 }
14959 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014960 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014961 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014962 } else
14963 return (1);
14964 return (ret);
14965}
14966
14967/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014968 * xmlSchemaHasElemContent:
14969 * @node: the node
14970 *
14971 * Scours the content of the given node for element
14972 * nodes.
14973 *
14974 * Returns 1 if an element node is found,
14975 * 0 otherwise.
14976 */
14977static int
14978xmlSchemaHasElemContent(xmlNodePtr node)
14979{
14980 if (node == NULL)
14981 return (0);
14982 node = node->children;
14983 while (node != NULL) {
14984 if (node->type == XML_ELEMENT_NODE)
14985 return (1);
14986 node = node->next;
14987 }
14988 return (0);
14989}
14990/**
14991 * xmlSchemaHasElemOrCharContent:
14992 * @node: the node
14993 *
14994 * Scours the content of the given node for element
14995 * and character nodes.
14996 *
14997 * Returns 1 if an element or character node is found,
14998 * 0 otherwise.
14999 */
15000static int
15001xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15002{
15003 if (node == NULL)
15004 return (0);
15005 node = node->children;
15006 while (node != NULL) {
15007 switch (node->type) {
15008 case XML_ELEMENT_NODE:
15009 /*
15010 * TODO: Ask Daniel if these are all character nodes.
15011 */
15012 case XML_TEXT_NODE:
15013 case XML_CDATA_SECTION_NODE:
15014 /*
15015 * TODO: How XML_ENTITY_NODEs evaluated?
15016 */
15017 case XML_ENTITY_REF_NODE:
15018 case XML_ENTITY_NODE:
15019 return (1);
15020 break;
15021 default:
15022 break;
15023 }
15024 node = node->next;
15025 }
15026 return (0);
15027}
15028
15029
15030/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015031 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015032 * @ctxt: a schema validation context
15033 * @node: the top node.
15034 *
15035 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015036 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015037 *
15038 * Returns 0 if the element is schemas valid, a positive error code
15039 * number otherwise and -1 in case of internal or API error.
15040 */
15041static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015042xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15043 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015044{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015045 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015046 int ret = 0;
15047 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015048 xmlAttrPtr attr;
15049 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015050 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015051
15052 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015053 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15054 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015055 * Note that @elemDecl will be the declaration and never the
15056 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015057 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015058
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015059 if (ctxt == NULL) {
15060 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15061 "Internal error: xmlSchemaValidateElementByDeclaration, "
15062 "bad arguments.\n",
15063 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015064 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015065 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015066
15067 elem = ctxt->node;
15068
15069 /*
15070 * cvc-elt (3.3.4) : 1
15071 */
15072 if (elemDecl == NULL) {
15073 xmlSchemaVCustomErr(ctxt,
15074 XML_SCHEMAV_CVC_ELT_1,
15075 elem, NULL,
15076 "No matching declaration available", NULL);
15077 return (ctxt->err);
15078 }
15079 /*
15080 * cvc-elt (3.3.4) : 2
15081 */
15082 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15083 xmlSchemaVCustomErr(ctxt,
15084 XML_SCHEMAV_CVC_ELT_2,
15085 elem, NULL,
15086 "The element declaration is abstract", NULL);
15087 return (ctxt->err);
15088 }
15089
15090 /*
15091 * cvc-elt (3.3.4) : 3
15092 * Handle 'xsi:nil'.
15093 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015094
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015095 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015096 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015097 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15098 ctxt->node = (xmlNodePtr) attr;
15099 ctxt->cur = attr->children;
15100 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15101 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15102 BAD_CAST attrValue, 1, 1, 1, 1);
15103 ctxt->node = elem;
15104 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15105 if (ret < 0) {
15106 xmlSchemaVCustomErr(ctxt,
15107 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015108 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015109 "Internal error: xmlSchemaValidateElementByDeclaration, "
15110 "validating the attribute 'xsi:nil'", NULL);
15111 if (attrValue != NULL)
15112 xmlFree(attrValue);
15113 return (-1);
15114 }
15115 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015116 /*
15117 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015118 */
15119 xmlSchemaVCustomErr(ctxt,
15120 XML_SCHEMAV_CVC_ELT_3_1,
15121 elem, NULL,
15122 "The element is not 'nillable'", NULL);
15123 } else {
15124 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015125 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015126 ret = 0;
15127 /*
15128 * cvc-elt (3.3.4) : 3.2.1
15129 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015130 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15131 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015132 xmlSchemaVCustomErr(ctxt,
15133 XML_SCHEMAV_CVC_ELT_3_2_1,
15134 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015135 elem, (xmlSchemaTypePtr) elemDecl,
15136 "The 'nilled' element must have no character or "
15137 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015138 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15139 }
15140 /*
15141 * cvc-elt (3.3.4) : 3.2.2
15142 */
15143 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15144 (elemDecl->value != NULL)) {
15145 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15146 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015147 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015148 "There is a fixed value constraint defined for "
15149 "the 'nilled' element", NULL);
15150 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15151 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015152 if (ret == 0)
15153 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015154 }
15155 }
15156 if (attrValue != NULL)
15157 xmlFree(attrValue);
15158 }
15159
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015160
15161 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015162 /*
15163 * cvc-elt (3.3.4) : 4
15164 * Handle 'xsi:type'.
15165 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015166
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015167 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15168 if (attr != NULL) {
15169 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015170
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015171 /*
15172 * TODO: We should report a *warning* that the type was overriden
15173 * by the instance.
15174 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015175
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015176 /*
15177 * cvc-elt (3.3.4) : 4.1
15178 */
15179 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15180 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15181 &nsName, &local);
15182 if (ret < 0) {
15183 xmlSchemaVCustomErr(ctxt,
15184 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015185 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015186 "Internal error: xmlSchemaValidateElementByDeclaration, "
15187 "validating the attribute 'xsi:type'", NULL);;
15188 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015189 FREE_AND_NULL(nsName)
15190 FREE_AND_NULL(local)
15191 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015192 } else if (ret == 1) {
15193 xmlSchemaVSimpleTypeErr(ctxt,
15194 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15195 (xmlNodePtr) attr, attrValue,
15196 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15197 } else if (ret == 2) {
15198 xmlSchemaVCustomErr(ctxt,
15199 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15200 (xmlNodePtr) attr,
15201 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15202 "The QName value '%s' has no "
15203 "corresponding namespace declaration in scope",
15204 attrValue);
15205 } else {
15206 /*
15207 * cvc-elt (3.3.4) : 4.2
15208 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015209 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15210 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015211 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015212
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015213 xmlSchemaVCustomErr(ctxt,
15214 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015215 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015216 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15217 "The value %s does not resolve to a type "
15218 "definition",
15219 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15220 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015221 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015222 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015223 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015224 */
15225 }
15226 }
15227 FREE_AND_NULL(attrValue)
15228 FREE_AND_NULL(nsName)
15229 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015230 }
15231 /* TODO: Change the handling of missing types according to
15232 * the spec.
15233 */
15234 if (actualType == NULL) {
15235 xmlSchemaVComplexTypeErr(ctxt,
15236 XML_SCHEMAV_CVC_TYPE_1,
15237 elem, (xmlSchemaTypePtr) elemDecl,
15238 "The type definition is absent");
15239 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015240 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015241
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015242 /*
15243 * TODO: Since this should be already checked by the content model automaton,
15244 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15245 * has been changed to XML_SCHEMAV_INTERNAL.
15246 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015247 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015248 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015249 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015250 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015251 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015252 "Element %s: missing child %s\n",
15253 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015254 }
15255 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015256 }
15257 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015258 /*
15259 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015260 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015261 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015262 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015263 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015264 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015265 "Element %s: missing child %s found %s\n",
15266 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015267 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015269 */
15270 if (elemHasContent == -1)
15271 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15272 /*
15273 * cvc-elt (3.3.4) : 5
15274 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015275 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015276 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015277 * cvc-elt (3.3.4) : 5.1
15278 * If the declaration has a {value constraint},
15279 * the item has neither element nor character [children] and
15280 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015281 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015282 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15283 /*
15284 * cvc-elt (3.3.4) : 5.1.1
15285 * If the ·actual type definition· is a ·local type definition·
15286 * then the canonical lexical representation of the {value constraint}
15287 * value must be a valid default for the ·actual type definition· as
15288 * defined in Element Default Valid (Immediate) (§3.3.6).
15289 */
15290 /*
15291 * NOTE: 'local' above means types aquired by xsi:type.
15292 */
15293 ret = 0;
15294 if (actualType != elemDecl->subtypes) {
15295 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15296 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15297 elemDecl->value, NULL);
15298 if (ret < 0) {
15299 xmlSchemaVCustomErr(ctxt,
15300 XML_SCHEMAV_INTERNAL,
15301 elem, actualType,
15302 "Internal error: xmlSchemaValidateElementByDeclaration, "
15303 "validating a default value", NULL);
15304 return (-1);
15305 }
15306 }
15307 /*
15308 * cvc-elt (3.3.4) : 5.1.2
15309 * The element information item with the canonical lexical
15310 * representation of the {value constraint} value used as its
15311 * ·normalized value· must be ·valid· with respect to the
15312 * ·actual type definition· as defined by Element Locally Valid (Type)
15313 * (§3.3.4).
15314 */
15315 /*
15316 * Disable validation of the simple content, since it was already
15317 * done above.
15318 */
15319 if (ret == 0) {
15320 if (actualType != elemDecl->subtypes)
15321 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15322 else
15323 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15324 ctxt->node = elem;
15325 if (ret < 0) {
15326 xmlSchemaVCustomErr(ctxt,
15327 XML_SCHEMAV_INTERNAL,
15328 elem, actualType,
15329 "Internal error: xmlSchemaValidateElementByDeclaration, "
15330 "validating against the type", NULL);
15331 return (-1);
15332 }
15333 /*
15334 * PSVI: Create a text node on the instance element.
15335 */
15336 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15337 xmlNodePtr textChild;
15338
15339 textChild = xmlNewText(elemDecl->value);
15340 if (textChild == NULL) {
15341 xmlSchemaVCustomErr(ctxt,
15342 XML_SCHEMAV_INTERNAL,
15343 elem, actualType,
15344 "Internal error: xmlSchemaValidateElementByDeclaration, "
15345 "could not create a default text node for the instance",
15346 NULL);
15347 } else
15348 xmlAddChild(elem, textChild);
15349 }
15350 }
15351
15352 } else {
15353 /*
15354 * 5.2.1 The element information item must be ·valid· with respect
15355 * to the ·actual type definition· as defined by Element Locally
15356 * Valid (Type) (§3.3.4).
15357 */
15358 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15359 ctxt->node = elem;
15360 if (ret < 0) {
15361 xmlSchemaVCustomErr(ctxt,
15362 XML_SCHEMAV_INTERNAL,
15363 elem, actualType,
15364 "Internal error: xmlSchemaValidateElementByDeclaration, "
15365 "validating a default value", NULL);
15366 return (-1);
15367 }
15368 /*
15369 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15370 * not applied, all of the following must be true:
15371 */
15372
15373 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15374 /*
15375 * 5.2.2.1 The element information item must have no element
15376 * information item [children].
15377 *
15378 * TODO REDUNDANT: If the actual type exists, the above call to
15379 * xmlSchemaValidateElementByType will already check for element
15380 * nodes.
15381 */
15382 if (xmlSchemaHasElemContent(elem)) {
15383 xmlSchemaVCustomErr(ctxt,
15384 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15385 elem, (xmlSchemaTypePtr) elemDecl,
15386 "Elements in the content are not allowed if it is "
15387 "constrained by a fixed value", NULL);
15388 } else {
15389 /*
15390 * 5.2.2.2 The appropriate case among the following must
15391 * be true:
15392 */
15393
15394 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15395 xmlChar *value;
15396 /*
15397 * 5.2.2.2.1 If the {content type} of the ·actual type
15398 * definition· is mixed, then the *initial value* of the
15399 * item must match the canonical lexical representation
15400 * of the {value constraint} value.
15401 *
15402 * ... the *initial value* of an element information
15403 * item is the string composed of, in order, the
15404 * [character code] of each character information item in
15405 * the [children] of that element information item.
15406 */
15407 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15408 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15409 /*
15410 * TODO: Report invalid & expected values as well.
15411 * TODO: Implement the cononical stuff.
15412 */
15413 xmlSchemaVCustomErr(ctxt,
15414 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15415 elem, (xmlSchemaTypePtr) elemDecl,
15416 "The value does not match the cononical "
15417 "lexical representation of the fixed constraint",
15418 NULL);
15419 }
15420 if (value != NULL)
15421 xmlFree(value);
15422 } else if ((actualType->contentType ==
15423 XML_SCHEMA_CONTENT_SIMPLE) ||
15424 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15425 xmlChar *value;
15426
15427 /*
15428 * 5.2.2.2.2 If the {content type} of the ·actual type
15429 * definition· is a simple type definition, then the
15430 * *actual value* of the item must match the canonical
15431 * lexical representation of the {value constraint} value.
15432 */
15433 /*
15434 * TODO: *actual value* is the normalized value, impl. this.
15435 * TODO: Report invalid & expected values as well.
15436 * TODO: Implement the cononical stuff.
15437 *
15438 */
15439 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15440 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15441 xmlSchemaVCustomErr(ctxt,
15442 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15443 elem, (xmlSchemaTypePtr) elemDecl,
15444 "The normalized value does not match the cononical "
15445 "lexical representation of the fixed constraint",
15446 NULL);
15447 }
15448 if (value != NULL)
15449 xmlFree(value);
15450
15451 }
15452 /*
15453 * TODO: What if the content type is not 'mixed' or simple?
15454 */
15455
15456 }
15457
15458 }
15459 }
15460
15461 /*
15462 * TODO: 6 The element information item must be ·valid· with respect to each of
15463 * the {identity-constraint definitions} as per Identity-constraint
15464 * Satisfied (§3.11.4).
15465 */
15466
15467 /*
15468 * TODO: 7 If the element information item is the ·validation root·, it must be
15469 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15470 */
15471
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015472 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015473}
15474
Daniel Veillard4255d502002-04-16 15:50:10 +000015475/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015476 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015477 * @ctxt: a schema validation context
15478 * @node: the top node.
15479 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015480 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15481 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015482 *
15483 * Returns 0 if the element is valid, a positive error code
15484 * number otherwise and -1 in case of an internal error.
15485 */
15486static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015487xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15488 xmlSchemaWildcardPtr wild,
15489 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015490{
15491 const xmlChar *uri;
15492 int ret = 0;
15493 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015494
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015495 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015496 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15497 if (ret == -1) {
15498 xmlSchemaVCustomErr(ctxt,
15499 XML_SCHEMAV_INTERNAL,
15500 ctxt->node, NULL,
15501 "Internal error: xmlSchemaValidateElement, "
15502 "assembling schema by xsi", NULL);
15503 return (-1);
15504 }
15505 /*
15506 * NOTE: We won't react on schema parser errors here.
15507 * TODO: But a warning would be nice.
15508 */
15509 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015510 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15511 xmlSchemaElementPtr decl = NULL;
15512
15513 if (node->ns != NULL)
15514 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15515 node->name, node->ns->href, NULL);
15516 else
15517 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15518 if (decl != NULL) {
15519 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015520 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015521 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015522 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015523 "Internal error: xmlSchemaValidateAnyInternal, "
15524 "validating an element in the context of a wildcard.",
15525 NULL, NULL);
15526 } else if (ret > 0)
15527 return (ret);
15528 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15529 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015530 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015531 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015532 return (ctxt->err);
15533 }
15534 }
15535 if (node->children != NULL) {
15536 child = node->children;
15537 do {
15538 if (child->type == XML_ELEMENT_NODE) {
15539 if (child->ns != NULL)
15540 uri = child->ns->href;
15541 else
15542 uri = NULL;
15543 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015544 /* TODO: error code. */
15545 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015546 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015547 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015548 return (ctxt->err);
15549 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015550 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15551 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015552 if (ret != 0)
15553 return (ret);
15554 }
15555 child = child->next;
15556 } while (child != NULL);
15557 }
15558 return (0);
15559}
15560
15561/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015562 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015563 * @ctxt: a schema validation context
15564 *
15565 * Returns 0 if the element is valid, a positive error code
15566 * number otherwise and -1 in case of an internal or API error.
15567 */
15568static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015569xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15570 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015571{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015572 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15573 (ctxt->node == NULL)) {
15574 xmlSchemaVCustomErr(ctxt,
15575 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15576 "Internal error: xmlSchemaValidateElementByWildcard, "
15577 "bad arguments", NULL);
15578 return (-1);
15579 }
15580 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15581 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015582}
15583
15584/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015585 * xmlSchemaValidateAnyTypeContent:
15586 * @ctxt: a schema validation context
15587 * @node: the current element
15588 *
15589 * This one validates the content of an element of the type
15590 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15591 * thus elements in the subtree will be validated, if a corresponding
15592 * declaration in the schema exists.
15593 *
15594 * Returns 0 if the element and its subtree is valid, a positive error code
15595 * otherwise and -1 in case of an internal or API error.
15596 */
15597static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015598xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15599 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015600{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015601 xmlSchemaTypePtr oldtype;
15602 xmlNodePtr top, cur;
15603 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015604 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015605
15606 if ((type == NULL) || (ctxt->node == NULL))
15607 return (-1);
15608
15609 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015610 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015611
15612 oldtype = ctxt->type;
15613 top = ctxt->node;
15614 /*
15615 * STREAM: Child nodes are processed.
15616 */
15617 cur = ctxt->node->children;
15618 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015619 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015620 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015621 /*
15622 * The process contents of the wildcard is "lax", thus
15623 * we need to validate the element if a declaration
15624 * exists.
15625 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015626 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015627 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015628 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015629 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015630 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015631 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015632 ctxt->node = cur;
15633 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15634 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015635 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015636 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015637 "Internal error: xmlSchemaValidateAnyTypeContent, "
15638 "validating an element in the context of a wildcard.",
15639 NULL, NULL);
15640 return (ret);
15641 } else if (ret > 0)
15642 return (ret);
15643 skipContent = 1;
15644 }
15645 }
15646 /*
15647 * Browse the full subtree, deep first.
15648 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015649 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015650 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015651 cur = cur->children;
15652 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015653 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015654 cur = cur->next;
15655 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015656 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015657 while (cur != top) {
15658 if (cur->parent != NULL)
15659 cur = cur->parent;
15660 if ((cur != top) && (cur->next != NULL)) {
15661 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015662 break;
15663 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015664 if (cur->parent == NULL) {
15665 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015666 break;
15667 }
15668 }
15669 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015670 if (cur == top)
15671 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015672 } else
15673 break;
15674 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015675 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015676 return (0);
15677}
15678
15679/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015680 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015681 * @ctxt: a schema validation context
15682 * @node: the top node.
15683 *
15684 * Validate the content of an element expected to be a complex type type
15685 * xmlschema-1.html#cvc-complex-type
15686 * Validation Rule: Element Locally Valid (Complex Type)
15687 *
15688 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015689 * number otherwise and -1 in case of internal or API error.
15690 * Note on reported errors: Although it might be nice to report
15691 * the name of the simple/complex type, used to validate the content
15692 * of a node, it is quite unnecessary: for global defined types
15693 * the local name of the element is equal to the NCName of the type,
15694 * for local defined types it makes no sense to output the internal
15695 * computed name of the type. TODO: Instead, one should attach the
15696 * struct of the type involved to the error handler - this allows
15697 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015698 */
15699static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015700xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015701 xmlSchemaTypePtr type,
15702 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015703{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015704 xmlSchemaTypePtr oldtype;
15705 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015706 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015707 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015708 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015709
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015710 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15711 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015712
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015713 oldtype = ctxt->type;
15714 ctxt->type = type;
15715 elem = ctxt->node;
15716
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015717 /*
15718 * Verify the attributes
15719 */
15720 /*
15721 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015722 */
15723 /* NOTE: removed, since a check for abstract is
15724 * done in the cvc-type constraint.
15725 *
15726 *
15727 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15728 * xmlSchemaVComplexTypeErr(ctxt,
15729 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15730 * elem, type,
15731 * "The type definition is abstract");
15732 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15733 *}
15734 */
15735
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015736 attrs = ctxt->attr;
15737 attrTop = ctxt->attrTop;
15738 /*
15739 * STREAM: Attribute nodes are processed.
15740 */
15741 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15742 xmlSchemaValidateAttributes(ctxt, elem, type);
15743 if (ctxt->attr != NULL)
15744 xmlSchemaFreeAttributeStates(ctxt->attr);
15745 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015746 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015747
15748 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015749 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015750 * model was defined. Somehow ->contModel is always not NULL
15751 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015752 * TODO: Check if the obove still occurs.
15753 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015754 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015755 case XML_SCHEMA_CONTENT_EMPTY: {
15756 /*
15757 * 1 If the {content type} is empty, then the element information
15758 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015759 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015760 /*
15761 * TODO: Is the entity stuff correct?
15762 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015763 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015764 xmlSchemaVComplexTypeErr(ctxt,
15765 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015766 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015767 "Character or element content is not allowed, "
15768 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015769 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015770 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015771 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015772 case XML_SCHEMA_CONTENT_MIXED:
15773 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015774 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015775 /*
15776 * The type has 'anyType' as its base and no content model
15777 * is defined -> use 'anyType' as the type to validate
15778 * against.
15779 */
15780 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15781 /* TODO: Handle -1. */
15782 break;
15783 }
15784 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015785 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015786 {
15787 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015788
15789 /*
15790 * Content model check initialization.
15791 */
15792 if (type->contModel != NULL) {
15793 oldregexp = ctxt->regexp;
15794 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15795 (xmlRegExecCallbacks)
15796 xmlSchemaValidateCallback, ctxt);
15797#ifdef DEBUG_AUTOMATA
15798 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15799#endif
15800 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015801 /*
15802 * STREAM: Children are processed.
15803 */
15804 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015805 while (child != NULL) {
15806 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015807 if (child->ns != NULL)
15808 nsUri = child->ns->href;
15809 else
15810 nsUri = NULL;
15811 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015812 child->name, nsUri, child);
15813 /*
15814 * URGENT TODO: Could we anchor an error report
15815 * here to notify of invalid elements?
15816 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015817#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000015818 if (ret < 0)
15819 xmlGenericError(xmlGenericErrorContext,
15820 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000015821 else
15822 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015823 " --> %s\n", child->name);
15824#endif
15825 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
15826 /*
15827 * TODO: Ask Daniel if this are all character nodes.
15828 */
15829 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
15830 (child->type == XML_ENTITY_NODE) ||
15831 (child->type == XML_ENTITY_REF_NODE) ||
15832 (child->type == XML_CDATA_SECTION_NODE))) {
15833 /*
15834 * 2.3 If the {content type} is element-only, then the
15835 * element information item has no character information
15836 * item [children] other than those whose [character
15837 * code] is defined as a white space in [XML 1.0 (Second
15838 * Edition)].
15839 */
William M. Brack2f2a6632004-08-20 23:09:47 +000015840 xmlSchemaVComplexTypeErr(ctxt,
15841 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015842 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015843 "Character content is not allowed, "
15844 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015845 break;
15846 }
15847 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015848 }
15849 /*
15850 * Content model check finalization.
15851 */
15852 if (type->contModel != NULL) {
15853 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
15854#ifdef DEBUG_AUTOMATA
15855 xmlGenericError(xmlGenericErrorContext,
15856 "====> %s : %d\n", elem->name, ret);
15857#endif
15858 if (ret == 0) {
15859 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15860 elem, type, "The element content is not valid", NULL);
15861 } else if (ret < 0) {
15862 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15863 elem, type, "The element content is not valid", NULL);
15864#ifdef DEBUG_CONTENT
15865 } else {
15866 xmlGenericError(xmlGenericErrorContext,
15867 "Element %s content check succeeded\n",
15868 elem->name);
15869
15870#endif
15871 }
15872 xmlRegFreeExecCtxt(ctxt->regexp);
15873 ctxt->regexp = oldregexp;
15874 }
15875 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015876 break;
15877 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015878 case XML_SCHEMA_CONTENT_BASIC:
15879 /*
15880 * If the simple content was already validated
15881 * (e.g. a default value), the content need not
15882 * to be validated again.
15883 */
15884 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015885 xmlChar *value = NULL;
15886 /*
15887 * We hit a complexType with a simpleContent resolving
15888 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000015889 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015890 /*
15891 * 2.2 If the {content type} is a simple type definition,
15892 * then the element information item has no element
15893 * information item [children], and the ·normalized value·
15894 * of the element information item is ·valid· with respect
15895 * to that simple type definition as defined by String
15896 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015897 */
15898 /*
15899 * STREAM: Children are processed.
15900 */
15901 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015902 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015903 /*
15904 * TODO: Could the entity stuff produce elements
15905 * as well?
15906 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015907 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015908 xmlSchemaVComplexTypeErr(ctxt,
15909 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015910 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015911 "Element content is not allowed, because "
15912 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015913 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15914 break;
15915 }
15916 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015917 }
15918 ctxt->node = elem;
15919 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015920 if (ret == 0) {
15921 /*
15922 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000015923 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015924 /*
15925 * STREAM: Children are processed.
15926 */
15927 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015928 value = NULL;
15929 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015930 value = xmlNodeGetContent(elem);
15931 /*
15932 * URGENT TODO: Should facets for the simple type validation be
15933 * disabled, if the derivation of facets for complex types
15934 * is implemented?
15935 */
15936 /*
15937 * NOTE: This call won't check the correct types of the
15938 * content nodes, since this should be done here.
15939 */
15940 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015941 if (ret > 0) {
15942 /*
15943 * NOTE: Although an error will be reported by
15944 * xmlSchemaValidateSimpleTypeValue, the spec wants
15945 * a specific complex type error to be reported
15946 * additionally.
15947 */
15948 xmlSchemaVComplexTypeErr(ctxt,
15949 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015950 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015951 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015952 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15953 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015954 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015955 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015956 "Element '%s': Error while validating character "
15957 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015958 elem->name, type->name);
15959 if (value != NULL)
15960 xmlFree(value);
15961 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015962 return (-1);
15963 }
William M. Brack2f2a6632004-08-20 23:09:47 +000015964 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015965 if (ret == 0) {
15966 /*
15967 * Apply facets of the complexType. Be sure to pass the
15968 * built-in type to xmlSchemaValidateFacetsInternal.
15969 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015970 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000015971 * are used, or if the facets, defined by this complex type,
15972 * are to be used only. This here applies both facet sets.
15973 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015974
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015975 ret = xmlSchemaValidateFacetsInternal(ctxt,
15976 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015977 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015978 xmlSchemaVComplexTypeErr(ctxt,
15979 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015980 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015981 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015982 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15983 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015984 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015985 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015986 "Element '%s': Error while validating character "
15987 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000015988 "apply facets.\n",
15989 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015990 if (value != NULL)
15991 xmlFree(value);
15992 ctxt->type = oldtype;
15993 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015994 }
15995 }
15996 if (value != NULL)
15997 xmlFree(value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015998
Daniel Veillard01fa6152004-06-29 17:04:39 +000015999 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016000 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016001 default:
16002 TODO xmlGenericError(xmlGenericErrorContext,
16003 "unimplemented content type %d\n",
16004 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016005 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016006 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016007 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016008}
16009
16010/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016011 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016012 * @ctxt: a schema validation context
16013 * @elem: an element
16014 * @type: the list of type declarations
16015 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016016 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016017 *
16018 * Returns 0 if the element is schemas valid, a positive error code
16019 * number otherwise and -1 in case of internal or API error.
16020 */
16021static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016022xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016023 xmlSchemaTypePtr type,
16024 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016025{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016026 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016027
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016028
16029 if ((ctxt == NULL) || (type == NULL)) {
16030 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16031 "Internal error: xmlSchemaValidateElementByType, "
16032 "bad arguments", NULL);
16033 return (-1);
16034 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016035 /*
16036 * This one is called by "xmlSchemaValidateElementByDeclaration".
16037 * It will forward to the proper validation
16038 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016039 */
16040 if (type == NULL) {
16041 xmlSchemaVComplexTypeErr(ctxt,
16042 XML_SCHEMAV_CVC_TYPE_1,
16043 ctxt->node, NULL,
16044 "The type definition is absent");
16045 return (XML_SCHEMAV_CVC_TYPE_1);
16046 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016047
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016048 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
16049 xmlSchemaVComplexTypeErr(ctxt,
16050 XML_SCHEMAV_CVC_TYPE_2,
16051 ctxt->node, type,
16052 "The type definition is abstract");
16053 return (XML_SCHEMAV_CVC_TYPE_2);
16054 }
16055
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016056 switch (type->type) {
16057 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016058 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16059 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016060 break;
16061 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016062 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16063 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016064 break;
16065 case XML_SCHEMA_TYPE_BASIC:
16066 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16067 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16068 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016069 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16070 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016071 break;
16072 default:
16073 ret = -1;
16074 break;
16075 }
16076 if (ret == -1)
16077 return (-1);
16078 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016079 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016080}
16081
16082
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016083static int
16084xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16085 xmlSchemaAttributePtr decl,
16086 xmlSchemaAttrStatePtr state,
16087 xmlAttrPtr attr)
16088{
16089 xmlChar *value;
16090 const xmlChar *defValue;
16091 xmlSchemaValPtr defVal;
16092 int fixed;
16093 int ret;
16094
16095 if (decl->subtypes == NULL) {
16096 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16097 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16098 }
16099 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16100 ctxt->node = (xmlNodePtr) attr;
16101 ctxt->cur = attr->children;
16102 /*
16103 * NOTE: This call also checks the content nodes for correct type.
16104 */
16105 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16106 value, 1, 1, 1, 1);
16107
16108 /*
16109 * Handle 'fixed' attributes.
16110 */
16111 if (ret > 0) {
16112 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16113 /*
16114 * NOTE: Fixed value constraints will be not
16115 * applied if the value was invalid, because:
16116 * 1. The validation process does not return a precomputed
16117 * value.
16118 * 2. An invalid value implies a violation of a fixed
16119 * value constraint.
16120 */
16121 } else if (ret == 0) {
16122 state->state = XML_SCHEMAS_ATTR_CHECKED;
16123 if (xmlSchemaGetEffectiveValueConstraint(decl,
16124 &fixed, &defValue, &defVal) && (fixed == 1)) {
16125 /*
16126 * cvc-au : Attribute Locally Valid (Use)
16127 * For an attribute information item to be·valid·
16128 * with respect to an attribute use its ·normalized
16129 * value· must match the canonical lexical representation
16130 * of the attribute use's {value constraint} value, if it
16131 * is present and fixed.
16132 */
16133 /*
16134 * NOTE: the validation context holds in ctxt->value the
16135 * precomputed value of the attribute; well for some types,
16136 * fallback to string comparison if no computed value
16137 * exists.
16138 */
16139 if (((ctxt->value != NULL) &&
16140 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16141 ((ctxt->value == NULL) &&
16142 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16143 state->state =
16144 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16145 }
16146 }
16147 }
16148 if (value != NULL) {
16149 xmlFree(value);
16150 }
16151 return (ret);
16152}
16153
Daniel Veillard4255d502002-04-16 15:50:10 +000016154/**
16155 * xmlSchemaValidateAttributes:
16156 * @ctxt: a schema validation context
16157 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016158 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016159 *
16160 * Validate the attributes of an element.
16161 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016162 * 1. Existent, invalid attributes are reported in the form
16163 * "prefix:localName".
16164 * Reason: readability - it is easier to find the actual XML
16165 * representation of the attributes QName.
16166 * 2. Missing attributes are reported in the form
16167 * {"URI", "localName"}.
16168 * This is necessary, since the the prefix need not to be declared
16169 * at all, and thus is not computable.
16170 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016171 * Returns 0 if the element is schemas valid, a positive error code
16172 * number otherwise and -1 in case of internal or API error.
16173 */
16174static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016175xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016176{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016177 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016178 int ret;
16179 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016180 const xmlChar *defValue;
16181 xmlSchemaValPtr defVal;
16182 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016183 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016184 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016185 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016186 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016187 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016188 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016189#ifdef DEBUG_ATTR_VALIDATION
16190 int redundant = 0;
16191#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016192
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016193
Daniel Veillardc0826a72004-08-10 14:17:33 +000016194 /*
16195 * Allow all attributes if the type is anyType.
16196 */
16197 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16198 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016199
16200 oldnode = ctxt->node;
16201 if (type != NULL)
16202 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016203 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016204 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016205 attrDecl = attrUse->attr;
16206#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016207 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016208 printf("attr use - use: %d\n", attrDecl->occurs);
16209#endif
16210 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16211
16212 if (curState->decl == attrUse->attr) {
16213#ifdef DEBUG_ATTR_VALIDATION
16214 redundant = 1;
16215#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016216 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016217 attr = curState->attr;
16218#ifdef DEBUG_ATTR_VALIDATION
16219 printf("attr - name: %s\n", attr->name);
16220 if (attr->ns != NULL)
16221 printf("attr - ns: %s\n", attr->ns->href);
16222 else
16223 printf("attr - ns: none\n");
16224#endif
16225 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016226 if (attr == NULL)
16227 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016228 if (attrDecl->ref != NULL) {
16229 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016230 continue;
16231 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016232 if ((attrDecl->refNs == NULL) ||
16233 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016234 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016235 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016236 continue;
16237 }
16238 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016239 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016240 continue;
16241 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016242 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016243 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016244 if (attr->ns == NULL) {
16245 /*
William M. Bracke7091952004-05-11 15:09:58 +000016246 * accept an unqualified attribute only if the target
16247 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016248 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016249 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016250 /*
16251 * This check was removed, since the target namespace
16252 * was evaluated during parsing and already took
16253 * "attributeFormDefault" into account.
16254 */
16255 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016256 continue;
16257 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016258 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016259 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016260 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016261 attr->ns->href))
16262 continue;
16263 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016264 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016265#ifdef DEBUG_ATTR_VALIDATION
16266 printf("found\n");
16267#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016268 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016269 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016270 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016271 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016272 if (!found) {
16273 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16274 xmlSchemaAttrStatePtr tmp;
16275
Daniel Veillard3646d642004-06-02 19:19:14 +000016276#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016277 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016278#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016279 /*
16280 * Add a new dummy attribute state.
16281 */
16282 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16283 if (tmp == NULL) {
16284 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16285 ctxt->node = oldnode;
16286 return (-1);
16287 }
16288 tmp->attr = NULL;
16289 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16290 tmp->decl = attrDecl;
16291 tmp->next = NULL;
16292
16293 if (reqAttrStates == NULL) {
16294 reqAttrStates = tmp;
16295 reqAttrStatesTop = tmp;
16296 } else {
16297 reqAttrStatesTop->next = tmp;
16298 reqAttrStatesTop = tmp;
16299 }
16300 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16301 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16302 &fixed, &defValue, &defVal))) {
16303 xmlSchemaAttrStatePtr tmp;
16304 /*
16305 * Handle non existent default/fixed attributes.
16306 */
16307 tmp = (xmlSchemaAttrStatePtr)
16308 xmlMalloc(sizeof(xmlSchemaAttrState));
16309 if (tmp == NULL) {
16310 xmlSchemaVErrMemory(ctxt,
16311 "registering schema specified attributes", NULL);
16312 ctxt->node = oldnode;
16313 return (-1);
16314 }
16315 tmp->attr = NULL;
16316 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16317 tmp->decl = attrDecl;
16318 tmp->value = defValue;
16319 tmp->next = NULL;
16320
16321 if (defAttrStates == NULL) {
16322 defAttrStates = tmp;
16323 defAttrStates = tmp;
16324 } else {
16325 defAttrStates->next = tmp;
16326 defAttrStatesTop = tmp;
16327 }
16328 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016329 }
16330 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016331 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016332 /*
16333 * Add required attributes to the attribute states of the context.
16334 */
16335 if (reqAttrStates != NULL) {
16336 if (ctxt->attr == NULL) {
16337 ctxt->attr = reqAttrStates;
16338 } else {
16339 ctxt->attrTop->next = reqAttrStates;
16340 }
16341 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016342 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016343 /*
16344 * Process wildcards.
16345 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016346
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016347 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016348#ifdef DEBUG_ATTR_VALIDATION
16349 xmlSchemaWildcardNsPtr ns;
16350 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016351 if (type->attributeWildcard->processContents ==
16352 XML_SCHEMAS_ANY_LAX)
16353 printf("processContents: lax\n");
16354 else if (type->attributeWildcard->processContents ==
16355 XML_SCHEMAS_ANY_STRICT)
16356 printf("processContents: strict\n");
16357 else
16358 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016359 if (type->attributeWildcard->any)
16360 printf("type: any\n");
16361 else if (type->attributeWildcard->negNsSet != NULL) {
16362 printf("type: negated\n");
16363 if (type->attributeWildcard->negNsSet->value == NULL)
16364 printf("ns: (absent)\n");
16365 else
16366 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16367 } else if (type->attributeWildcard->nsSet != NULL) {
16368 printf("type: set\n");
16369 ns = type->attributeWildcard->nsSet;
16370 while (ns != NULL) {
16371 if (ns->value == NULL)
16372 printf("ns: (absent)\n");
16373 else
16374 printf("ns: %s\n", ns->value);
16375 ns = ns->next;
16376 }
16377 } else
16378 printf("empty\n");
16379
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016380
16381#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016382 curState = ctxt->attr;
16383 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016384 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16385 if (curState->attr->ns != NULL)
16386 nsURI = curState->attr->ns->href;
16387 else
16388 nsURI = NULL;
16389 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16390 nsURI)) {
16391 /*
16392 * Handle processContents.
16393 */
16394 if ((type->attributeWildcard->processContents ==
16395 XML_SCHEMAS_ANY_LAX) ||
16396 (type->attributeWildcard->processContents ==
16397 XML_SCHEMAS_ANY_STRICT)) {
16398
16399 attr = curState->attr;
16400 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016401 attr->name, nsURI);
16402 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016403 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016404 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016405 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016406 } else if (type->attributeWildcard->processContents ==
16407 XML_SCHEMAS_ANY_LAX) {
16408 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16409 }
16410 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016411 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016412 }
16413 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016414 curState = curState->next;
16415 }
16416 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016417
Daniel Veillardc0826a72004-08-10 14:17:33 +000016418 /*
16419 * Report missing and illegal attributes.
16420 */
16421 if (ctxt->attr != NULL) {
16422 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016423 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016424 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16425 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016426 if (curState->decl != NULL) {
16427 if (curState->decl->ref != NULL)
16428 attrDecl = curState->decl->refDecl;
16429 else
16430 attrDecl = curState->decl;
16431 } else
16432 attrDecl = NULL;
16433 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16434 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16435 } else if (curState->state ==
16436 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16437 xmlSchemaVCustomErr(ctxt,
16438 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16439 (xmlNodePtr) attr,
16440 (xmlSchemaTypePtr) attrDecl,
16441 "The type definition is absent",
16442 NULL);
16443 } else if (curState->state ==
16444 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16445 xmlSchemaVCustomErr(ctxt,
16446 XML_SCHEMAV_CVC_AU,
16447 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16448 "The value does not match the fixed value "
16449 "constraint", NULL);
16450 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016451 /* TODO: "prohibited" won't ever be touched here!.
16452 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16453 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016454 /*
16455 * TODO: One might report different error messages
16456 * for the following errors.
16457 */
16458 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016459 xmlSchemaVIllegalAttrErr(ctxt,
16460 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16461 } else {
16462 xmlSchemaVIllegalAttrErr(ctxt,
16463 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16464 }
16465 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016466 }
16467 curState = curState->next;
16468 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016469 }
16470
16471 /*
16472 * Add missing default/fixed attributes.
16473 */
16474 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16475 curState = defAttrStates;
16476 while (curState != NULL) {
16477 attrDecl = curState->decl;
16478 if (attrDecl->ref != NULL)
16479 attrDecl = attrDecl->refDecl;
16480 /*
16481 * PSVI: Add a new attribute node to the current element.
16482 */
16483 if (attrDecl->targetNamespace == NULL) {
16484 xmlNewProp(elem, attrDecl->name, curState->value);
16485 } else {
16486 xmlNsPtr ns;
16487
16488 ns = xmlSearchNsByHref(elem->doc, elem,
16489 attrDecl->targetNamespace);
16490 if (ns == NULL) {
16491 xmlChar prefix[12];
16492 int counter = 1;
16493
16494 attr = curState->attr;
16495 /*
16496 * Create a namespace declaration on the validation
16497 * root node if no namespace declaration is in scope.
16498 */
16499 snprintf((char *) prefix, sizeof(prefix), "p");
16500 /*
16501 * This is somehow not performant, since the ancestor
16502 * axis beyond @elem will be searched as well.
16503 */
16504 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16505 while (ns != NULL) {
16506 if (counter > 1000) {
16507 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16508 XML_SCHEMAV_INTERNAL,
16509 "Internal error: xmlSchemaValidateAttributes, "
16510 "could not compute a ns prefix for "
16511 "default/fixed attribute '%s'.\n",
16512 attrDecl->name, NULL);
16513
16514 break;
16515 }
16516 snprintf((char *) prefix,
16517 sizeof(prefix), "p%d", counter++);
16518 ns = xmlSearchNs(elem->doc, elem,
16519 BAD_CAST prefix);
16520 }
16521 if (ns == NULL) {
16522 ns = xmlNewNs(ctxt->validationRoot,
16523 attrDecl->targetNamespace, BAD_CAST prefix);
16524 xmlNewNsProp(elem, ns, attrDecl->name,
16525 curState->value);
16526 }
16527 } else {
16528 xmlNewNsProp(elem, ns, attrDecl->name,
16529 curState->value);
16530 }
16531 }
16532 curState = curState->next;
16533 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016534 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016535 if (defAttrStates != NULL)
16536 xmlSchemaFreeAttributeStates(defAttrStates);
16537
Daniel Veillard3646d642004-06-02 19:19:14 +000016538#ifdef DEBUG_ATTR_VALIDATION
16539 if (redundant)
16540 xmlGenericError(xmlGenericErrorContext,
16541 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16542 type->name);
16543#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016544 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016545 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016546}
16547
16548/**
16549 * xmlSchemaValidateElement:
16550 * @ctxt: a schema validation context
16551 * @elem: an element
16552 *
16553 * Validate an element in a tree
16554 *
16555 * Returns 0 if the element is schemas valid, a positive error code
16556 * number otherwise and -1 in case of internal or API error.
16557 */
16558static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016559xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016560{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016561 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016562 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016563
Daniel Veillardc0826a72004-08-10 14:17:33 +000016564 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016565 * This one is called by xmlSchemaValidateDocument and
16566 * xmlSchemaValidateOneElement.
16567 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016568 if (ctxt->schema == NULL) {
16569 /*
16570 * No schema was specified at time of creation of the validation
16571 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16572 * of the instance to build a schema.
16573 */
16574 if (ctxt->pctxt == NULL)
16575 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16576 if (ctxt->pctxt == NULL)
16577 return (-1);
16578 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16579 if (ctxt->schema == NULL)
16580 return (-1);
16581 /* TODO: assign user data. */
16582 ctxt->pctxt->error = ctxt->error;
16583 ctxt->pctxt->warning = ctxt->warning;
16584 ctxt->xsiAssemble = 1;
16585 } else
16586 ctxt->xsiAssemble = 0;
16587 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16588 * ctxt->xsiAssemble = 1;
16589 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016590 /*
16591 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016592 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016593 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016594 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16595 if (ret == -1) {
16596 xmlSchemaVCustomErr(ctxt,
16597 XML_SCHEMAV_INTERNAL,
16598 ctxt->node, NULL,
16599 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016600 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016601 }
16602 /*
16603 * NOTE: We won't react on schema parser errors here.
16604 * TODO: But a warning would be nice.
16605 */
16606 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016607 if (ret != -1) {
16608 if (ctxt->node->ns != NULL)
16609 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16610 ctxt->node->ns->href);
16611 else
16612 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16613
16614 if (elemDecl == NULL) {
16615 xmlSchemaVCustomErr(ctxt,
16616 XML_SCHEMAV_CVC_ELT_1,
16617 ctxt->node, NULL,
16618 "No matching global declaration available", NULL);
16619 ret = XML_SCHEMAV_CVC_ELT_1;
16620 } else {
16621 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16622 if (ret < 0) {
16623 xmlSchemaVCustomErr(ctxt,
16624 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16625 "Internal error: xmlSchemaValidateElement, "
16626 "calling validation by declaration", NULL);
16627 }
16628 }
16629 }
16630 /* ctxt->xsiAssemble = 0; */
16631 if (ctxt->xsiAssemble) {
16632 if (ctxt->schema != NULL) {
16633 xmlSchemaFree(ctxt->schema);
16634 ctxt->schema = NULL;
16635 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016636 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016637 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016638}
16639
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016640
Daniel Veillard4255d502002-04-16 15:50:10 +000016641/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016642 * xmlSchemaValidateOneElement:
16643 * @ctxt: a schema validation context
16644 * @elem: an element node
16645 *
16646 * Validate a branch of a tree, starting with the given @elem.
16647 *
16648 * Returns 0 if the element and its subtree is valid, a positive error
16649 * code number otherwise and -1 in case of an internal or API error.
16650 */
16651int
16652xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16653{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016654 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016655 return (-1);
16656
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016657 if (ctxt->schema == NULL) {
16658 xmlSchemaVErr(ctxt, NULL,
16659 XML_SCHEMAV_INTERNAL,
16660 "API error: xmlSchemaValidateOneElement, "
16661 "no schema specified.\n", NULL, NULL);
16662 return (-1);
16663 }
16664
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016665 ctxt->doc = elem->doc;
16666 ctxt->err = 0;
16667 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016668 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016669 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016670 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016671}
16672
16673/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016674 * xmlSchemaValidateDocument:
16675 * @ctxt: a schema validation context
16676 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016677 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016678 *
16679 * Validate a document tree in memory.
16680 *
16681 * Returns 0 if the document is schemas valid, a positive error code
16682 * number otherwise and -1 in case of internal or API error.
16683 */
16684static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016685xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16686{
Daniel Veillard4255d502002-04-16 15:50:10 +000016687 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016688
Daniel Veillard4255d502002-04-16 15:50:10 +000016689 root = xmlDocGetRootElement(doc);
16690 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016691 xmlSchemaVCustomErr(ctxt,
16692 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16693 (xmlNodePtr) doc, NULL,
16694 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016695 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016696 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016697 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016698 /*
16699 * Okay, start the recursive validation
16700 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016701 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016702 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016703 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016704
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016705 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016706}
16707
16708/************************************************************************
16709 * *
16710 * SAX Validation code *
16711 * *
16712 ************************************************************************/
16713
16714/************************************************************************
16715 * *
16716 * Validation interfaces *
16717 * *
16718 ************************************************************************/
16719
16720/**
16721 * xmlSchemaNewValidCtxt:
16722 * @schema: a precompiled XML Schemas
16723 *
16724 * Create an XML Schemas validation context based on the given schema
16725 *
16726 * Returns the validation context or NULL in case of error
16727 */
16728xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016729xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16730{
Daniel Veillard4255d502002-04-16 15:50:10 +000016731 xmlSchemaValidCtxtPtr ret;
16732
16733 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16734 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016735 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016736 return (NULL);
16737 }
16738 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016739 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016740 ret->attrTop = NULL;
16741 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016742 return (ret);
16743}
16744
16745/**
16746 * xmlSchemaFreeValidCtxt:
16747 * @ctxt: the schema validation context
16748 *
16749 * Free the resources associated to the schema validation context
16750 */
16751void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016752xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16753{
Daniel Veillard4255d502002-04-16 15:50:10 +000016754 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016755 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016756 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016757 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016758 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016759 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016760 if (ctxt->pctxt != NULL) {
16761 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16762 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016763 xmlFree(ctxt);
16764}
16765
16766/**
16767 * xmlSchemaSetValidErrors:
16768 * @ctxt: a schema validation context
16769 * @err: the error function
16770 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016771 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016772 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016773 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016774 */
16775void
16776xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016777 xmlSchemaValidityErrorFunc err,
16778 xmlSchemaValidityWarningFunc warn, void *ctx)
16779{
Daniel Veillard4255d502002-04-16 15:50:10 +000016780 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016781 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016782 ctxt->error = err;
16783 ctxt->warning = warn;
16784 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016785 if (ctxt->pctxt != NULL)
16786 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000016787}
16788
16789/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016790 * xmlSchemaGetValidErrors:
16791 * @ctxt: a XML-Schema validation context
16792 * @err: the error function result
16793 * @warn: the warning function result
16794 * @ctx: the functions context result
16795 *
16796 * Get the error and warning callback informations
16797 *
16798 * Returns -1 in case of error and 0 otherwise
16799 */
16800int
16801xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
16802 xmlSchemaValidityErrorFunc * err,
16803 xmlSchemaValidityWarningFunc * warn, void **ctx)
16804{
16805 if (ctxt == NULL)
16806 return (-1);
16807 if (err != NULL)
16808 *err = ctxt->error;
16809 if (warn != NULL)
16810 *warn = ctxt->warning;
16811 if (ctx != NULL)
16812 *ctx = ctxt->userData;
16813 return (0);
16814}
16815
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016816
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016817/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016818 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016819 * @ctxt: a schema validation context
16820 * @options: a combination of xmlSchemaValidOption
16821 *
16822 * Sets the options to be used during the validation.
16823 *
16824 * Returns 0 in case of success, -1 in case of an
16825 * API error.
16826 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016827int
16828xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
16829 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016830
16831{
16832 int i;
16833
16834 if (ctxt == NULL)
16835 return (-1);
16836 /*
16837 * WARNING: Change the start value if adding to the
16838 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016839 * TODO: Is there an other, more easy to maintain,
16840 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016841 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016842 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016843 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016844 xmlSchemaVErr(ctxt, NULL,
16845 XML_SCHEMAV_INTERNAL,
16846 "Internal error: xmlSchemaSetValidOptions, "
16847 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016848 return (-1);
16849 }
16850 }
16851 ctxt->options = options;
16852 return (0);
16853}
16854
16855/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016856 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016857 * @ctxt: a schema validation context
16858 *
16859 * Returns the option combination of the validation context.
16860 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016861int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016862xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
16863
16864{
16865 if (ctxt == NULL)
16866 return (-1);
16867 else
16868 return (ctxt->options);
16869}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016870
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016871
Daniel Veillard259f0df2004-08-18 09:13:18 +000016872/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016873 * xmlSchemaValidateDoc:
16874 * @ctxt: a schema validation context
16875 * @doc: a parsed document tree
16876 *
16877 * Validate a document tree in memory.
16878 *
16879 * Returns 0 if the document is schemas valid, a positive error code
16880 * number otherwise and -1 in case of internal or API error.
16881 */
16882int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016883xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16884{
Daniel Veillard4255d502002-04-16 15:50:10 +000016885 int ret;
16886
16887 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016888 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016889
16890 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000016891 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016892 ctxt->nberrors = 0;
16893
16894 /*
16895 if (ctxt->schema == NULL) {
16896 xmlSchemaVErr(ctxt, NULL,
16897 XML_SCHEMAV_INTERNAL,
16898 "API error: xmlSchemaValidateDoc, "
16899 "no schema specified and assembling of schemata "
16900 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
16901 "is not enabled.\n", NULL, NULL);
16902 return (-1);
16903 }
16904 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016905 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016906 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016907}
16908
16909/**
16910 * xmlSchemaValidateStream:
16911 * @ctxt: a schema validation context
16912 * @input: the input to use for reading the data
16913 * @enc: an optional encoding information
16914 * @sax: a SAX handler for the resulting events
16915 * @user_data: the context to provide to the SAX handler.
16916 *
16917 * Validate a document tree in memory.
16918 *
16919 * Returns 0 if the document is schemas valid, a positive error code
16920 * number otherwise and -1 in case of internal or API error.
16921 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016922int
Daniel Veillard4255d502002-04-16 15:50:10 +000016923xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016924 xmlParserInputBufferPtr input, xmlCharEncoding enc,
16925 xmlSAXHandlerPtr sax, void *user_data)
16926{
Daniel Veillard4255d502002-04-16 15:50:10 +000016927 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016928 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016929 ctxt->input = input;
16930 ctxt->enc = enc;
16931 ctxt->sax = sax;
16932 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016933 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000016934}
16935
16936#endif /* LIBXML_SCHEMAS_ENABLED */