blob: cc9620e6bea43da09379c60888d54c6151566975 [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{
2437 if (schema == NULL) {
2438 fprintf(output, "Schemas: NULL\n");
2439 return;
2440 }
2441 fprintf(output, "Schemas: ");
2442 if (schema->name != NULL)
2443 fprintf(output, "%s, ", schema->name);
2444 else
2445 fprintf(output, "no name, ");
2446 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002447 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002448 else
2449 fprintf(output, "no target namespace");
2450 fprintf(output, "\n");
2451 if (schema->annot != NULL)
2452 xmlSchemaAnnotDump(output, schema->annot);
2453
2454 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2455 output);
2456 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002457 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002458}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002459#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002460
2461/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002462 * *
2463 * Utilities *
2464 * *
2465 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002466
Daniel Veillardc0826a72004-08-10 14:17:33 +00002467/**
2468 * xmlSchemaGetPropNode:
2469 * @node: the element node
2470 * @name: the name of the attribute
2471 *
2472 * Seeks an attribute with a name of @name in
2473 * no namespace.
2474 *
2475 * Returns the attribute or NULL if not present.
2476 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002477static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002478xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002479{
2480 xmlAttrPtr prop;
2481
Daniel Veillardc0826a72004-08-10 14:17:33 +00002482 if ((node == NULL) || (name == NULL))
2483 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002484 prop = node->properties;
2485 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002486 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2487 return(prop);
2488 prop = prop->next;
2489 }
2490 return (NULL);
2491}
2492
2493/**
2494 * xmlSchemaGetPropNodeNs:
2495 * @node: the element node
2496 * @uri: the uri
2497 * @name: the name of the attribute
2498 *
2499 * Seeks an attribute with a local name of @name and
2500 * a namespace URI of @uri.
2501 *
2502 * Returns the attribute or NULL if not present.
2503 */
2504static xmlAttrPtr
2505xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2506{
2507 xmlAttrPtr prop;
2508
2509 if ((node == NULL) || (name == NULL))
2510 return(NULL);
2511 prop = node->properties;
2512 while (prop != NULL) {
2513 if ((prop->ns != NULL) &&
2514 xmlStrEqual(prop->name, BAD_CAST name) &&
2515 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002516 return(prop);
2517 prop = prop->next;
2518 }
2519 return (NULL);
2520}
2521
2522static const xmlChar *
2523xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2524{
2525 xmlChar *val;
2526 const xmlChar *ret;
2527
2528 val = xmlNodeGetContent(node);
2529 if (val == NULL)
2530 return(NULL);
2531 ret = xmlDictLookup(ctxt->dict, val, -1);
2532 xmlFree(val);
2533 return(ret);
2534}
2535
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002536/**
2537 * xmlSchemaGetProp:
2538 * @ctxt: the parser context
2539 * @node: the node
2540 * @name: the property name
2541 *
2542 * Read a attribute value and internalize the string
2543 *
2544 * Returns the string or NULL if not present.
2545 */
2546static const xmlChar *
2547xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2548 const char *name)
2549{
2550 xmlChar *val;
2551 const xmlChar *ret;
2552
2553 val = xmlGetProp(node, BAD_CAST name);
2554 if (val == NULL)
2555 return(NULL);
2556 ret = xmlDictLookup(ctxt->dict, val, -1);
2557 xmlFree(val);
2558 return(ret);
2559}
2560
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002561/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002562 * *
2563 * Parsing functions *
2564 * *
2565 ************************************************************************/
2566
2567/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002568 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002569 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002570 * @name: the element name
2571 * @ns: the element namespace
2572 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002573 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002574 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002575 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002576 */
2577static xmlSchemaElementPtr
2578xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002579 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002580{
2581 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002582
2583 if ((name == NULL) || (schema == NULL))
2584 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002585
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002586 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002587 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002588 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002589 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002590 } else
2591 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002592 /*
2593 * This one was removed, since top level element declarations have
2594 * the target namespace specified in targetNamespace of the <schema>
2595 * information element, even if elementFormDefault is "unqualified".
2596 */
2597
2598 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002599 if (xmlStrEqual(namespace, schema->targetNamespace))
2600 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2601 else
2602 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002603 if ((ret != NULL) &&
2604 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002605 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002606 }
William M. Bracke7091952004-05-11 15:09:58 +00002607 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002608
William M. Brack2f2a6632004-08-20 23:09:47 +00002609 /*
2610 * Removed since imported components will be hold by the main schema only.
2611 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002612 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002613 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002614 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002615 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002616 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002617 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002618 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2619 return (ret);
2620 } else
2621 ret = NULL;
2622 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002623 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002624#ifdef DEBUG
2625 if (ret == NULL) {
2626 if (namespace == NULL)
2627 fprintf(stderr, "Unable to lookup type %s", name);
2628 else
2629 fprintf(stderr, "Unable to lookup type %s:%s", name,
2630 namespace);
2631 }
2632#endif
2633 return (ret);
2634}
2635
2636/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002637 * xmlSchemaGetType:
2638 * @schema: the schemas context
2639 * @name: the type name
2640 * @ns: the type namespace
2641 *
2642 * Lookup a type in the schemas or the predefined types
2643 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002644 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002645 */
2646static xmlSchemaTypePtr
2647xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002648 const xmlChar * namespace)
2649{
Daniel Veillard4255d502002-04-16 15:50:10 +00002650 xmlSchemaTypePtr ret;
2651
2652 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002653 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002656 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002657 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002658 }
2659 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002660 if (ret != NULL)
2661 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002662 /*
2663 * Removed, since the imported components will be grafted on the
2664 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002665 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002666 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002667 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002668 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002669 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002670 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002671 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2672 return (ret);
2673 } else
2674 ret = NULL;
2675 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002676 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002677#ifdef DEBUG
2678 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002679 if (namespace == NULL)
2680 fprintf(stderr, "Unable to lookup type %s", name);
2681 else
2682 fprintf(stderr, "Unable to lookup type %s:%s", name,
2683 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002684 }
2685#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002687}
2688
Daniel Veillard3646d642004-06-02 19:19:14 +00002689/**
2690 * xmlSchemaGetAttribute:
2691 * @schema: the context of the schema
2692 * @name: the name of the attribute
2693 * @ns: the target namespace of the attribute
2694 *
2695 * Lookup a an attribute in the schema or imported schemas
2696 *
2697 * Returns the attribute declaration or NULL if not found.
2698 */
2699static xmlSchemaAttributePtr
2700xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2701 const xmlChar * namespace)
2702{
2703 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002704
2705 if ((name == NULL) || (schema == NULL))
2706 return (NULL);
2707
2708
2709 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2710 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2711 return (ret);
2712 else
2713 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002714 /*
2715 * Removed, since imported components will be hold by the main schema only.
2716 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002717 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002718 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002719 else
2720 import = xmlHashLookup(schema->schemasImports, namespace);
2721 if (import != NULL) {
2722 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2723 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2724 return (ret);
2725 } else
2726 ret = NULL;
2727 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002728 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002729#ifdef DEBUG
2730 if (ret == NULL) {
2731 if (namespace == NULL)
2732 fprintf(stderr, "Unable to lookup attribute %s", name);
2733 else
2734 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2735 namespace);
2736 }
2737#endif
2738 return (ret);
2739}
2740
2741/**
2742 * xmlSchemaGetAttributeGroup:
2743 * @schema: the context of the schema
2744 * @name: the name of the attribute group
2745 * @ns: the target namespace of the attribute group
2746 *
2747 * Lookup a an attribute group in the schema or imported schemas
2748 *
2749 * Returns the attribute group definition or NULL if not found.
2750 */
2751static xmlSchemaAttributeGroupPtr
2752xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2753 const xmlChar * namespace)
2754{
2755 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002756
2757 if ((name == NULL) || (schema == NULL))
2758 return (NULL);
2759
2760
2761 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2762 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2763 return (ret);
2764 else
2765 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002766 /*
2767 * Removed since imported components will be hold by the main schema only.
2768 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002769 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002770 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002771 else
2772 import = xmlHashLookup(schema->schemasImports, namespace);
2773 if (import != NULL) {
2774 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2775 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2776 return (ret);
2777 else
2778 ret = NULL;
2779 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002780 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002781#ifdef DEBUG
2782 if (ret == NULL) {
2783 if (namespace == NULL)
2784 fprintf(stderr, "Unable to lookup attribute group %s", name);
2785 else
2786 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2787 namespace);
2788 }
2789#endif
2790 return (ret);
2791}
2792
2793/**
2794 * xmlSchemaGetGroup:
2795 * @schema: the context of the schema
2796 * @name: the name of the group
2797 * @ns: the target namespace of the group
2798 *
2799 * Lookup a group in the schema or imported schemas
2800 *
2801 * Returns the group definition or NULL if not found.
2802 */
2803static xmlSchemaTypePtr
2804xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2805 const xmlChar * namespace)
2806{
2807 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002808
2809 if ((name == NULL) || (schema == NULL))
2810 return (NULL);
2811
2812
2813 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2814 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2815 return (ret);
2816 else
2817 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002818 /*
2819 * Removed since imported components will be hold by the main schema only.
2820 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002821 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002822 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002823 else
2824 import = xmlHashLookup(schema->schemasImports, namespace);
2825 if (import != NULL) {
2826 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2827 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2828 return (ret);
2829 else
2830 ret = NULL;
2831 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002832 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002833#ifdef DEBUG
2834 if (ret == NULL) {
2835 if (namespace == NULL)
2836 fprintf(stderr, "Unable to lookup group %s", name);
2837 else
2838 fprintf(stderr, "Unable to lookup group %s:%s", name,
2839 namespace);
2840 }
2841#endif
2842 return (ret);
2843}
2844
Daniel Veillard4255d502002-04-16 15:50:10 +00002845/************************************************************************
2846 * *
2847 * Parsing functions *
2848 * *
2849 ************************************************************************/
2850
2851#define IS_BLANK_NODE(n) \
2852 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2853
2854/**
2855 * xmlSchemaIsBlank:
2856 * @str: a string
2857 *
2858 * Check if a string is ignorable
2859 *
2860 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2861 */
2862static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002863xmlSchemaIsBlank(xmlChar * str)
2864{
Daniel Veillard4255d502002-04-16 15:50:10 +00002865 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002866 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002867 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002868 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002869 return (0);
2870 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002871 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002872 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002873}
2874
2875/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002876 * xmlSchemaAddAssembledItem:
2877 * @ctxt: a schema parser context
2878 * @schema: the schema being built
2879 * @item: the item
2880 *
2881 * Add a item to the schema's list of current items.
2882 * This is used if the schema was already constructed and
2883 * new schemata need to be added to it.
2884 * *WARNING* this interface is highly subject to change.
2885 *
2886 * Returns 0 if suceeds and -1 if an internal error occurs.
2887 */
2888static int
2889xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
2890 xmlSchemaTypePtr item)
2891{
2892 static int growSize = 100;
2893 xmlSchemaAssemblePtr ass;
2894
2895 ass = ctxt->assemble;
2896 if (ass->sizeItems < 0) {
2897 /* If disabled. */
2898 return (0);
2899 }
2900 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002901 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002902 if (ass->items == NULL) {
2903 xmlSchemaPErrMemory(ctxt,
2904 "allocating new item buffer", NULL);
2905 return (-1);
2906 }
2907 ass->sizeItems = growSize;
2908 } else if (ass->sizeItems <= ass->nbItems) {
2909 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002910 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002911 ass->sizeItems * sizeof(xmlSchemaTypePtr));
2912 if (ass->items == NULL) {
2913 xmlSchemaPErrMemory(ctxt,
2914 "growing item buffer", NULL);
2915 ass->sizeItems = 0;
2916 return (-1);
2917 }
2918 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002919 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002920 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
2921 return (0);
2922}
2923
2924/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002925 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002926 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002927 * @schema: the schema being built
2928 * @name: the item name
2929 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002930 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002931 * *WARNING* this interface is highly subject to change
2932 *
2933 * Returns the new struture or NULL in case of error
2934 */
2935static xmlSchemaNotationPtr
2936xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002937 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002938{
2939 xmlSchemaNotationPtr ret = NULL;
2940 int val;
2941
2942 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2943 return (NULL);
2944
2945 if (schema->notaDecl == NULL)
2946 schema->notaDecl = xmlHashCreate(10);
2947 if (schema->notaDecl == NULL)
2948 return (NULL);
2949
2950 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2951 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002952 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002953 return (NULL);
2954 }
2955 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002956 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002957 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2958 ret);
2959 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002960 /*
2961 * TODO: This should never happen, since a unique name will be computed.
2962 * If it fails, then an other internal error must have occured.
2963 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002964 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2965 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002966 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002967 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002968 xmlFree(ret);
2969 return (NULL);
2970 }
2971 return (ret);
2972}
2973
2974
2975/**
2976 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002977 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002978 * @schema: the schema being built
2979 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002980 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002981 *
2982 * Add an XML schema Attrribute declaration
2983 * *WARNING* this interface is highly subject to change
2984 *
2985 * Returns the new struture or NULL in case of error
2986 */
2987static xmlSchemaAttributePtr
2988xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002989 const xmlChar * name, const xmlChar * namespace,
2990 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002991{
2992 xmlSchemaAttributePtr ret = NULL;
2993 int val;
2994
2995 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2996 return (NULL);
2997
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002998#ifdef DEBUG
2999 fprintf(stderr, "Adding attribute %s\n", name);
3000 if (namespace != NULL)
3001 fprintf(stderr, " target namespace %s\n", namespace);
3002#endif
3003
Daniel Veillard4255d502002-04-16 15:50:10 +00003004 if (schema->attrDecl == NULL)
3005 schema->attrDecl = xmlHashCreate(10);
3006 if (schema->attrDecl == NULL)
3007 return (NULL);
3008
3009 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3010 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003011 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003012 return (NULL);
3013 }
3014 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003015 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3016 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003017 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003018 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003020 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003021 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003022 NULL, NULL, node,
3023 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003024 xmlFree(ret);
3025 return (NULL);
3026 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003027 if (ctxt->assemble != NULL)
3028 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003029 return (ret);
3030}
3031
3032/**
3033 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003034 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003035 * @schema: the schema being built
3036 * @name: the item name
3037 *
3038 * Add an XML schema Attrribute Group declaration
3039 *
3040 * Returns the new struture or NULL in case of error
3041 */
3042static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003043xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003044 xmlSchemaPtr schema, const xmlChar * name,
3045 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003046{
3047 xmlSchemaAttributeGroupPtr ret = NULL;
3048 int val;
3049
3050 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3051 return (NULL);
3052
3053 if (schema->attrgrpDecl == NULL)
3054 schema->attrgrpDecl = xmlHashCreate(10);
3055 if (schema->attrgrpDecl == NULL)
3056 return (NULL);
3057
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003058 ret =
3059 (xmlSchemaAttributeGroupPtr)
3060 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003061 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003062 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003063 return (NULL);
3064 }
3065 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003066 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003067 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003068 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003069 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003070 xmlSchemaPCustomErr(ctxt,
3071 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3072 NULL, NULL, node,
3073 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003074 xmlFree(ret);
3075 return (NULL);
3076 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003077 if (ctxt->assemble != NULL)
3078 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003079 return (ret);
3080}
3081
3082/**
3083 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003084 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003085 * @schema: the schema being built
3086 * @name: the type name
3087 * @namespace: the type namespace
3088 *
3089 * Add an XML schema Element declaration
3090 * *WARNING* this interface is highly subject to change
3091 *
3092 * Returns the new struture or NULL in case of error
3093 */
3094static xmlSchemaElementPtr
3095xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003096 const xmlChar * name, const xmlChar * namespace,
3097 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003098{
3099 xmlSchemaElementPtr ret = NULL;
3100 int val;
3101
3102 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3103 return (NULL);
3104
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003105#ifdef DEBUG
3106 fprintf(stderr, "Adding element %s\n", name);
3107 if (namespace != NULL)
3108 fprintf(stderr, " target namespace %s\n", namespace);
3109#endif
3110
Daniel Veillard4255d502002-04-16 15:50:10 +00003111 if (schema->elemDecl == NULL)
3112 schema->elemDecl = xmlHashCreate(10);
3113 if (schema->elemDecl == NULL)
3114 return (NULL);
3115
3116 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3117 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003118 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003119 return (NULL);
3120 }
3121 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003122 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3123 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003124 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003125 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003126 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003127 if (topLevel) {
3128 xmlSchemaPCustomErr(ctxt,
3129 XML_SCHEMAP_REDEFINED_ELEMENT,
3130 NULL, NULL, node,
3131 "A global element declaration with the name '%s' does "
3132 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003133 xmlFree(ret);
3134 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003135 } else {
3136 char buf[30];
3137
3138 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3139 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3140 namespace, ret);
3141 if (val != 0) {
3142 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003143 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003144 NULL, NULL, node,
3145 "Internal error: xmlSchemaAddElement, "
3146 "a dublicate element declaration with the name '%s' "
3147 "could not be added to the hash.", name);
3148 xmlFree(ret);
3149 return (NULL);
3150 }
3151 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003152
Daniel Veillard4255d502002-04-16 15:50:10 +00003153 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003154 if (ctxt->assemble != NULL)
3155 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003156 return (ret);
3157}
3158
3159/**
3160 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003161 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003162 * @schema: the schema being built
3163 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003164 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003165 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003166 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003167 * *WARNING* this interface is highly subject to change
3168 *
3169 * Returns the new struture or NULL in case of error
3170 */
3171static xmlSchemaTypePtr
3172xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003173 const xmlChar * name, const xmlChar * namespace,
3174 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003175{
3176 xmlSchemaTypePtr ret = NULL;
3177 int val;
3178
3179 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3180 return (NULL);
3181
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003182#ifdef DEBUG
3183 fprintf(stderr, "Adding type %s\n", name);
3184 if (namespace != NULL)
3185 fprintf(stderr, " target namespace %s\n", namespace);
3186#endif
3187
Daniel Veillard4255d502002-04-16 15:50:10 +00003188 if (schema->typeDecl == NULL)
3189 schema->typeDecl = xmlHashCreate(10);
3190 if (schema->typeDecl == NULL)
3191 return (NULL);
3192
3193 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3194 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003195 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003196 return (NULL);
3197 }
3198 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003199 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003200 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003201 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003202 if (val != 0) {
3203 if (ctxt->includes == 0) {
3204 xmlSchemaPCustomErr(ctxt,
3205 XML_SCHEMAP_REDEFINED_TYPE,
3206 NULL, NULL, node,
3207 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003208 xmlFree(ret);
3209 return (NULL);
3210 } else {
3211 xmlSchemaTypePtr prev;
3212
3213 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3214 if (prev == NULL) {
3215 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003216 XML_ERR_INTERNAL_ERROR,
3217 "Internal error: xmlSchemaAddType, on type "
3218 "'%s'.\n",
3219 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003220 xmlFree(ret);
3221 return (NULL);
3222 }
3223 ret->redef = prev->redef;
3224 prev->redef = ret;
3225 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003226 }
3227 ret->minOccurs = 1;
3228 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003229 ret->attributeUses = NULL;
3230 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003231 if (ctxt->assemble != NULL)
3232 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003233 return (ret);
3234}
3235
3236/**
3237 * xmlSchemaAddGroup:
3238 * @ctxt: a schema validation context
3239 * @schema: the schema being built
3240 * @name: the group name
3241 *
3242 * Add an XML schema Group definition
3243 *
3244 * Returns the new struture or NULL in case of error
3245 */
3246static xmlSchemaTypePtr
3247xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003248 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003249{
3250 xmlSchemaTypePtr ret = NULL;
3251 int val;
3252
3253 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3254 return (NULL);
3255
3256 if (schema->groupDecl == NULL)
3257 schema->groupDecl = xmlHashCreate(10);
3258 if (schema->groupDecl == NULL)
3259 return (NULL);
3260
3261 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3262 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003263 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003264 return (NULL);
3265 }
3266 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003267 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003268 val =
3269 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3270 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003271 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003272 xmlSchemaPCustomErr(ctxt,
3273 XML_SCHEMAP_REDEFINED_GROUP,
3274 NULL, NULL, node,
3275 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003276 xmlFree(ret);
3277 return (NULL);
3278 }
3279 ret->minOccurs = 1;
3280 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003281 if (ctxt->assemble != NULL)
3282 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003283 return (ret);
3284}
3285
Daniel Veillard3646d642004-06-02 19:19:14 +00003286/**
3287 * xmlSchemaNewWildcardNs:
3288 * @ctxt: a schema validation context
3289 *
3290 * Creates a new wildcard namespace constraint.
3291 *
3292 * Returns the new struture or NULL in case of error
3293 */
3294static xmlSchemaWildcardNsPtr
3295xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3296{
3297 xmlSchemaWildcardNsPtr ret;
3298
3299 ret = (xmlSchemaWildcardNsPtr)
3300 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3301 if (ret == NULL) {
3302 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3303 return (NULL);
3304 }
3305 ret->value = NULL;
3306 ret->next = NULL;
3307 return (ret);
3308}
3309
3310/**
3311 * xmlSchemaAddWildcard:
3312 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003313 * Adds a wildcard. It corresponds to a
3314 * xsd:anyAttribute and is used as storage for namespace
3315 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003316 *
3317 * Returns the new struture or NULL in case of error
3318 */
3319static xmlSchemaWildcardPtr
3320xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3321{
3322 xmlSchemaWildcardPtr ret = NULL;
3323
3324 if (ctxt == NULL)
3325 return (NULL);
3326
3327 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3328 if (ret == NULL) {
3329 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3330 return (NULL);
3331 }
3332 memset(ret, 0, sizeof(xmlSchemaWildcard));
3333 ret->minOccurs = 1;
3334 ret->maxOccurs = 1;
3335
3336 return (ret);
3337}
3338
Daniel Veillard4255d502002-04-16 15:50:10 +00003339/************************************************************************
3340 * *
3341 * Utilities for parsing *
3342 * *
3343 ************************************************************************/
3344
3345/**
3346 * xmlGetQNameProp:
3347 * @ctxt: a schema validation context
3348 * @node: a subtree containing XML Schema informations
3349 * @name: the attribute name
3350 * @namespace: the result namespace if any
3351 *
3352 * Extract a QName Attribute value
3353 *
3354 * Returns the NCName or NULL if not found, and also update @namespace
3355 * with the namespace URI
3356 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003357static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003358xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003359 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003360{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003361 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003362 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003363 const xmlChar *ret, *prefix;
3364 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003365 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003366
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003367 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003368 attr = xmlSchemaGetPropNode(node, name);
3369 if (attr == NULL)
3370 return (NULL);
3371 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003372
Daniel Veillard4255d502002-04-16 15:50:10 +00003373 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003374 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003375
Daniel Veillardba0153a2004-04-01 10:42:31 +00003376 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003377 ns = xmlSearchNs(node->doc, node, 0);
3378 if (ns) {
3379 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3380 return (val);
3381 }
3382 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003383 ret = xmlSplitQName3(val, &len);
3384 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003385 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003386 }
3387 ret = xmlDictLookup(ctxt->dict, ret, -1);
3388 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003389
3390 ns = xmlSearchNs(node->doc, node, prefix);
3391 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003392 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3393 NULL, NULL, (xmlNodePtr) attr,
3394 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003395 "The QName value '%s' has no corresponding namespace "
3396 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003397 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003398 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003400 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003401}
3402
3403/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003404 * xmlSchemaPValAttrNodeQNameValue:
3405 * @ctxt: a schema parser context
3406 * @schema: the schema context
3407 * @ownerDes: the designation of the parent element
3408 * @ownerItem: the parent as a schema object
3409 * @value: the QName value
3410 * @local: the resulting local part if found, the attribute value otherwise
3411 * @uri: the resulting namespace URI if found
3412 *
3413 * Extracts the local name and the URI of a QName value and validates it.
3414 * This one is intended to be used on attribute values that
3415 * should resolve to schema components.
3416 *
3417 * Returns 0, in case the QName is valid, a positive error code
3418 * if not valid and -1 if an internal error occurs.
3419 */
3420static int
3421xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3422 xmlSchemaPtr schema,
3423 xmlChar **ownerDes,
3424 xmlSchemaTypePtr ownerItem,
3425 xmlAttrPtr attr,
3426 const xmlChar *value,
3427 const xmlChar **uri,
3428 const xmlChar **prefix,
3429 const xmlChar **local)
3430{
3431 const xmlChar *pref;
3432 xmlNsPtr ns;
3433 int len, ret;
3434
3435 *uri = NULL;
3436 *local = NULL;
3437 if (prefix != 0)
3438 *prefix = NULL;
3439 ret = xmlValidateQName(value, 1);
3440 if (ret > 0) {
3441 xmlSchemaPSimpleTypeErr(ctxt,
3442 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3443 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003444 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3445 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003446 NULL, NULL, NULL);
3447 *local = value;
3448 return (ctxt->err);
3449 } else if (ret < 0)
3450 return (-1);
3451
3452 if (!strchr((char *) value, ':')) {
3453 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3454 if (ns)
3455 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3456 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3457 /*
3458 * This one takes care of included schemas with no
3459 * target namespace.
3460 */
3461 *uri = schema->targetNamespace;
3462 }
3463 *local = value;
3464 return (0);
3465 }
3466 /*
3467 * At this point xmlSplitQName3 has to return a local name.
3468 */
3469 *local = xmlSplitQName3(value, &len);
3470 *local = xmlDictLookup(ctxt->dict, *local, -1);
3471 pref = xmlDictLookup(ctxt->dict, value, len);
3472 if (prefix != 0)
3473 *prefix = pref;
3474 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3475 if (ns == NULL) {
3476 xmlSchemaPSimpleTypeErr(ctxt,
3477 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3478 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003479 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3480 "The QName value '%s' has no corresponding namespace "
3481 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003482 return (ctxt->err);
3483 } else {
3484 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3485 }
3486 return (0);
3487}
3488
3489/**
3490 * xmlSchemaPValAttrNodeQName:
3491 * @ctxt: a schema parser context
3492 * @schema: the schema context
3493 * @ownerDes: the designation of the owner element
3494 * @ownerItem: the owner as a schema object
3495 * @attr: the attribute node
3496 * @local: the resulting local part if found, the attribute value otherwise
3497 * @uri: the resulting namespace URI if found
3498 *
3499 * Extracts and validates the QName of an attribute value.
3500 * This one is intended to be used on attribute values that
3501 * should resolve to schema components.
3502 *
3503 * Returns 0, in case the QName is valid, a positive error code
3504 * if not valid and -1 if an internal error occurs.
3505 */
3506static int
3507xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3508 xmlSchemaPtr schema,
3509 xmlChar **ownerDes,
3510 xmlSchemaTypePtr ownerItem,
3511 xmlAttrPtr attr,
3512 const xmlChar **uri,
3513 const xmlChar **prefix,
3514 const xmlChar **local)
3515{
3516 const xmlChar *value;
3517
3518 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3519 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3520 ownerDes, ownerItem, attr, value, uri, prefix, local));
3521}
3522
3523/**
3524 * xmlSchemaPValAttrQName:
3525 * @ctxt: a schema parser context
3526 * @schema: the schema context
3527 * @ownerDes: the designation of the parent element
3528 * @ownerItem: the owner as a schema object
3529 * @ownerElem: the parent node of the attribute
3530 * @name: the name of the attribute
3531 * @local: the resulting local part if found, the attribute value otherwise
3532 * @uri: the resulting namespace URI if found
3533 *
3534 * Extracts and validates the QName of an attribute value.
3535 *
3536 * Returns 0, in case the QName is valid, a positive error code
3537 * if not valid and -1 if an internal error occurs.
3538 */
3539static int
3540xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3541 xmlSchemaPtr schema,
3542 xmlChar **ownerDes,
3543 xmlSchemaTypePtr ownerItem,
3544 xmlNodePtr ownerElem,
3545 const char *name,
3546 const xmlChar **uri,
3547 const xmlChar **prefix,
3548 const xmlChar **local)
3549{
3550 xmlAttrPtr attr;
3551
3552 attr = xmlSchemaGetPropNode(ownerElem, name);
3553 if (attr == NULL) {
3554 *local = NULL;
3555 *uri = NULL;
3556 return (0);
3557 }
3558 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3559 ownerDes, ownerItem, attr, uri, prefix, local));
3560}
3561
3562/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003563 * xmlGetMaxOccurs:
3564 * @ctxt: a schema validation context
3565 * @node: a subtree containing XML Schema informations
3566 *
3567 * Get the maxOccurs property
3568 *
3569 * Returns the default if not found, or the value
3570 */
3571static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003572xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3573 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003574{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003575 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003576 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003577 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003578
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003579 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3580 if (attr == NULL)
3581 return (def);
3582 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003583
3584 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003585 if (max != UNBOUNDED) {
3586 xmlSchemaPSimpleTypeErr(ctxt,
3587 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3588 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3589 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3590 val, NULL, NULL, NULL);
3591 return (def);
3592 } else
3593 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003594 }
3595
3596 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003597 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003598 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003599 if (*cur == 0) {
3600 xmlSchemaPSimpleTypeErr(ctxt,
3601 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3602 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3603 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3604 val, NULL, NULL, NULL);
3605 return (def);
3606 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003607 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003608 ret = ret * 10 + (*cur - '0');
3609 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003610 }
William M. Brack76e95df2003-10-18 16:20:14 +00003611 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003612 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003613 /*
3614 * TODO: Restrict the maximal value to Integer.
3615 */
3616 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3617 xmlSchemaPSimpleTypeErr(ctxt,
3618 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3619 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3620 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3621 val, NULL, NULL, NULL);
3622 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003625}
3626
3627/**
3628 * xmlGetMinOccurs:
3629 * @ctxt: a schema validation context
3630 * @node: a subtree containing XML Schema informations
3631 *
3632 * Get the minOccurs property
3633 *
3634 * Returns the default if not found, or the value
3635 */
3636static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003637xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3638 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003639{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003640 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003642 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003643
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003644 attr = xmlSchemaGetPropNode(node, "minOccurs");
3645 if (attr == NULL)
3646 return (def);
3647 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003649 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003651 if (*cur == 0) {
3652 xmlSchemaPSimpleTypeErr(ctxt,
3653 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3654 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3655 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3656 val, NULL, NULL, NULL);
3657 return (def);
3658 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003659 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003660 ret = ret * 10 + (*cur - '0');
3661 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003662 }
William M. Brack76e95df2003-10-18 16:20:14 +00003663 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003664 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003665 /*
3666 * TODO: Restrict the maximal value to Integer.
3667 */
3668 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3669 xmlSchemaPSimpleTypeErr(ctxt,
3670 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3671 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3672 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3673 val, NULL, NULL, NULL);
3674 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003675 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003676 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003677}
3678
3679/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003680 * xmlSchemaPGetBoolNodeValue:
3681 * @ctxt: a schema validation context
3682 * @ownerDes: owner designation
3683 * @ownerItem: the owner as a schema item
3684 * @node: the node holding the value
3685 *
3686 * Converts a boolean string value into 1 or 0.
3687 *
3688 * Returns 0 or 1.
3689 */
3690static int
3691xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3692 xmlChar **ownerDes,
3693 xmlSchemaTypePtr ownerItem,
3694 xmlNodePtr node)
3695{
3696 xmlChar *value = NULL;
3697 int res = 0;
3698
3699 value = xmlNodeGetContent(node);
3700 /*
3701 * 3.2.2.1 Lexical representation
3702 * An instance of a datatype that is defined as ·boolean·
3703 * can have the following legal literals {true, false, 1, 0}.
3704 */
3705 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3706 res = 1;
3707 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3708 res = 0;
3709 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3710 res = 1;
3711 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3712 res = 0;
3713 else {
3714 xmlSchemaPSimpleTypeErr(ctxt,
3715 XML_SCHEMAP_INVALID_BOOLEAN,
3716 ownerDes, ownerItem, node,
3717 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3718 "(1 | 0 | true | false)", BAD_CAST value,
3719 NULL, NULL, NULL);
3720 }
3721 if (value != NULL)
3722 xmlFree(value);
3723 return (res);
3724}
3725
3726/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003727 * xmlGetBooleanProp:
3728 * @ctxt: a schema validation context
3729 * @node: a subtree containing XML Schema informations
3730 * @name: the attribute name
3731 * @def: the default value
3732 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003733 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003734 *
3735 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003736 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003737 */
3738static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003739xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3740 xmlChar **ownerDes,
3741 xmlSchemaTypePtr ownerItem,
3742 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003743 const char *name, int def)
3744{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003745 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003746
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003747 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003748 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003749 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003750 /*
3751 * 3.2.2.1 Lexical representation
3752 * An instance of a datatype that is defined as ·boolean·
3753 * can have the following legal literals {true, false, 1, 0}.
3754 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003755 if (xmlStrEqual(val, BAD_CAST "true"))
3756 def = 1;
3757 else if (xmlStrEqual(val, BAD_CAST "false"))
3758 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003759 else if (xmlStrEqual(val, BAD_CAST "1"))
3760 def = 1;
3761 else if (xmlStrEqual(val, BAD_CAST "0"))
3762 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003763 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003764 xmlSchemaPSimpleTypeErr(ctxt,
3765 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003766 ownerDes, ownerItem, node,
3767 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3768 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003769 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003770 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003771}
3772
3773/************************************************************************
3774 * *
3775 * Shema extraction from an Infoset *
3776 * *
3777 ************************************************************************/
3778static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3779 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003780 xmlNodePtr node,
3781 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003782static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3783 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003785 xmlNodePtr node,
3786 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003787static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3788 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003789 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003790 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003791static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3792 xmlSchemaPtr schema,
3793 xmlNodePtr node);
3794static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3795 xmlSchemaPtr schema,
3796 xmlNodePtr node);
3797static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3798 ctxt,
3799 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003800 xmlNodePtr node,
3801 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003802static xmlSchemaAttributeGroupPtr
3803xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003804 xmlSchemaPtr schema, xmlNodePtr node,
3805 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003806static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3807 xmlSchemaPtr schema,
3808 xmlNodePtr node);
3809static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3810 xmlSchemaPtr schema,
3811 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003812static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003813xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3814 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003815
3816/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003817 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003818 *
3819 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003820 * @ownerDes: the designation of the parent element
3821 * @ownerItem: the schema object owner if existent
3822 * @attr: the schema attribute node being validated
3823 * @value: the value
3824 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003825 *
3826 * Validates a value against the given built-in type.
3827 * This one is intended to be used internally for validation
3828 * of schema attribute values during parsing of the schema.
3829 *
3830 * Returns 0 if the value is valid, a positive error code
3831 * number otherwise and -1 in case of an internal or API error.
3832 */
3833static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003834xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3835 xmlChar **ownerDes,
3836 xmlSchemaTypePtr ownerItem,
3837 xmlAttrPtr attr,
3838 const xmlChar *value,
3839 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003840{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003841
Daniel Veillardc0826a72004-08-10 14:17:33 +00003842 int ret = 0;
3843
3844 /*
3845 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3846 * one is really meant to be used internally, so better not.
3847 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003848 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003849 return (-1);
3850 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3851 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003852 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003853 "Internal error: xmlSchemaPvalueAttrNode, the given "
3854 "type '%s' is not a built-in type.\n",
3855 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003856 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003857 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003858 switch (type->builtInType) {
3859 case XML_SCHEMAS_NCNAME:
3860 ret = xmlValidateNCName(value, 1);
3861 break;
3862 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003863 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003864 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003865 "Internal error: xmlSchemaPvalueAttrNode, use "
3866 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3867 "for extracting QName valueues instead.\n",
3868 NULL, NULL);
3869 return (-1);
3870 case XML_SCHEMAS_ANYURI:
3871 if (value != NULL) {
3872 xmlURIPtr uri = xmlParseURI((const char *) value);
3873 if (uri == NULL)
3874 ret = 1;
3875 else
3876 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003877 }
3878 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003879 case XML_SCHEMAS_TOKEN: {
3880 const xmlChar *cur = value;
3881
3882 if (IS_BLANK_CH(*cur)) {
3883 ret = 1;
3884 } else while (*cur != 0) {
3885 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3886 ret = 1;
3887 break;
3888 } else if (*cur == ' ') {
3889 cur++;
3890 if ((*cur == 0) || (*cur == ' ')) {
3891 ret = 1;
3892 break;
3893 }
3894 } else {
3895 cur++;
3896 }
3897 }
3898 }
3899 break;
3900 case XML_SCHEMAS_LANGUAGE:
3901 if (xmlCheckLanguageID(value) != 1)
3902 ret = 1;
3903 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003904 default: {
3905 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003906 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003907 "Internal error: xmlSchemaPvalueAttrNode, "
3908 "valueidation using the type '%s' is not implemented "
3909 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003910 type->name, NULL);
3911 return (-1);
3912 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003913 }
3914 /*
3915 * TODO: Should we use the S4S error codes instead?
3916 */
3917 if (ret > 0) {
3918 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3919 xmlSchemaPSimpleTypeErr(ctxt,
3920 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3921 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003922 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003923 NULL, NULL, NULL);
3924 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3925 } else {
3926 xmlSchemaPSimpleTypeErr(ctxt,
3927 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3928 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003929 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003930 NULL, NULL, NULL);
3931 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3932 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003933 }
3934 return (ret);
3935}
3936
3937/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003938 * xmlSchemaPValAttrNode:
3939 *
3940 * @ctxt: a schema parser context
3941 * @ownerDes: the designation of the parent element
3942 * @ownerItem: the schema object owner if existent
3943 * @attr: the schema attribute node being validated
3944 * @type: the built-in type to be validated against
3945 * @value: the resulting value if any
3946 *
3947 * Extracts and validates a value against the given built-in type.
3948 * This one is intended to be used internally for validation
3949 * of schema attribute values during parsing of the schema.
3950 *
3951 * Returns 0 if the value is valid, a positive error code
3952 * number otherwise and -1 in case of an internal or API error.
3953 */
3954static int
3955xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3956 xmlChar **ownerDes,
3957 xmlSchemaTypePtr ownerItem,
3958 xmlAttrPtr attr,
3959 xmlSchemaTypePtr type,
3960 const xmlChar **value)
3961{
3962 const xmlChar *val;
3963
3964 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3965 return (-1);
3966
3967 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3968 if (value != NULL)
3969 *value = val;
3970
3971 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3972 val, type));
3973}
3974
3975/**
3976 * xmlSchemaPValAttr:
3977 *
3978 * @ctxt: a schema parser context
3979 * @node: the element node of the attribute
3980 * @ownerDes: the designation of the parent element
3981 * @ownerItem: the schema object owner if existent
3982 * @ownerElem: the owner element node
3983 * @name: the name of the schema attribute node
3984 * @type: the built-in type to be validated against
3985 * @value: the resulting value if any
3986 *
3987 * Extracts and validates a value against the given built-in type.
3988 * This one is intended to be used internally for validation
3989 * of schema attribute values during parsing of the schema.
3990 *
3991 * Returns 0 if the value is valid, a positive error code
3992 * number otherwise and -1 in case of an internal or API error.
3993 */
3994static int
3995xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3996 xmlChar **ownerDes,
3997 xmlSchemaTypePtr ownerItem,
3998 xmlNodePtr ownerElem,
3999 const char *name,
4000 xmlSchemaTypePtr type,
4001 const xmlChar **value)
4002{
4003 xmlAttrPtr attr;
4004
4005 if ((ctxt == NULL) || (type == NULL)) {
4006 if (value != NULL)
4007 *value = NULL;
4008 return (-1);
4009 }
4010 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4011 if (value != NULL)
4012 *value = NULL;
4013 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004014 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004015 "Internal error: xmlSchemaPValAttr, the given "
4016 "type '%s' is not a built-in type.\n",
4017 type->name, NULL);
4018 return (-1);
4019 }
4020 attr = xmlSchemaGetPropNode(ownerElem, name);
4021 if (attr == NULL) {
4022 if (value != NULL)
4023 *value = NULL;
4024 return (0);
4025 }
4026 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4027 type, value));
4028}
4029/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004030 * xmlSchemaParseAttrDecls:
4031 * @ctxt: a schema validation context
4032 * @schema: the schema being built
4033 * @node: a subtree containing XML Schema informations
4034 * @type: the hosting type
4035 *
4036 * parse a XML schema attrDecls declaration corresponding to
4037 * <!ENTITY % attrDecls
4038 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4039 */
4040static xmlNodePtr
4041xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4042 xmlNodePtr child, xmlSchemaTypePtr type)
4043{
4044 xmlSchemaAttributePtr lastattr, attr;
4045
4046 lastattr = NULL;
4047 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004048 (IS_SCHEMA(child, "attributeGroup"))) {
4049 attr = NULL;
4050 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004051 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004052 } else if (IS_SCHEMA(child, "attributeGroup")) {
4053 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004054 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004055 }
4056 if (attr != NULL) {
4057 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004058 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4059 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4060 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004061 type->attributes = attr;
4062 lastattr = attr;
4063 } else {
4064 lastattr->next = attr;
4065 lastattr = attr;
4066 }
4067 }
4068 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004069 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004070 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004071}
4072
4073/**
4074 * xmlSchemaParseAnnotation:
4075 * @ctxt: a schema validation context
4076 * @schema: the schema being built
4077 * @node: a subtree containing XML Schema informations
4078 *
4079 * parse a XML schema Attrribute declaration
4080 * *WARNING* this interface is highly subject to change
4081 *
William M. Bracke7091952004-05-11 15:09:58 +00004082 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004083 * 1 in case of success.
4084 */
4085static xmlSchemaAnnotPtr
4086xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4087 xmlNodePtr node)
4088{
4089 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004090 xmlNodePtr child = NULL;
4091 xmlAttrPtr attr;
4092 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004093
Daniel Veillardc0826a72004-08-10 14:17:33 +00004094 /*
4095 * INFO: S4S completed.
4096 */
4097 /*
4098 * id = ID
4099 * {any attributes with non-schema namespace . . .}>
4100 * Content: (appinfo | documentation)*
4101 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004102 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4103 return (NULL);
4104 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004105 attr = node->properties;
4106 while (attr != NULL) {
4107 if (((attr->ns == NULL) &&
4108 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4109 ((attr->ns != NULL) &&
4110 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4111
4112 xmlSchemaPIllegalAttrErr(ctxt,
4113 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4114 NULL, NULL, attr);
4115 }
4116 attr = attr->next;
4117 }
4118 /* TODO: Check id. */
4119
4120 /*
4121 * And now for the children...
4122 */
4123 child = node->children;
4124 while (child != NULL) {
4125 if (IS_SCHEMA(child, "appinfo")) {
4126 /* TODO: make available the content of "appinfo". */
4127 /*
4128 * source = anyURI
4129 * {any attributes with non-schema namespace . . .}>
4130 * Content: ({any})*
4131 */
4132 attr = child->properties;
4133 while (attr != NULL) {
4134 if (((attr->ns == NULL) &&
4135 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4136 ((attr->ns != NULL) &&
4137 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004138
Daniel Veillardc0826a72004-08-10 14:17:33 +00004139 xmlSchemaPIllegalAttrErr(ctxt,
4140 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4141 NULL, NULL, attr);
4142 }
4143 attr = attr->next;
4144 }
4145 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4146 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4147 child = child->next;
4148 } else if (IS_SCHEMA(child, "documentation")) {
4149 /* TODO: make available the content of "documentation". */
4150 /*
4151 * source = anyURI
4152 * {any attributes with non-schema namespace . . .}>
4153 * Content: ({any})*
4154 */
4155 attr = child->properties;
4156 while (attr != NULL) {
4157 if (attr->ns == NULL) {
4158 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4159 xmlSchemaPIllegalAttrErr(ctxt,
4160 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4161 NULL, NULL, attr);
4162 }
4163 } else {
4164 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4165 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4166 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4167
4168 xmlSchemaPIllegalAttrErr(ctxt,
4169 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4170 NULL, NULL, attr);
4171 }
4172 }
4173 attr = attr->next;
4174 }
4175 /*
4176 * Attribute "xml:lang".
4177 */
4178 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4179 if (attr != NULL)
4180 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4181 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4182 child = child->next;
4183 } else {
4184 if (!barked)
4185 xmlSchemaPContentErr(ctxt,
4186 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4187 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4188 barked = 1;
4189 child = child->next;
4190 }
4191 }
4192
Daniel Veillard4255d502002-04-16 15:50:10 +00004193 return (ret);
4194}
4195
4196/**
4197 * xmlSchemaParseFacet:
4198 * @ctxt: a schema validation context
4199 * @schema: the schema being built
4200 * @node: a subtree containing XML Schema informations
4201 *
4202 * parse a XML schema Facet declaration
4203 * *WARNING* this interface is highly subject to change
4204 *
4205 * Returns the new type structure or NULL in case of error
4206 */
4207static xmlSchemaFacetPtr
4208xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004209 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004210{
4211 xmlSchemaFacetPtr facet;
4212 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004213 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004214
4215 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4216 return (NULL);
4217
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004218 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004219 if (facet == NULL) {
4220 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4221 return (NULL);
4222 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004223 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004224 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004225 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004226 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4227 "Facet %s has no value\n", node->name, NULL);
4228 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004229 return (NULL);
4230 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004231 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004232 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004233 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004234 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004235 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004236 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004237 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004238 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004239 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004240 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004241 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004242 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004243 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004244 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004245 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004246 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004249 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004250 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004251 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004252 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4253 } else if (IS_SCHEMA(node, "minLength")) {
4254 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4255 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004256 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4257 "Unknown facet type %s\n", node->name, NULL);
4258 xmlSchemaFreeFacet(facet);
4259 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004260 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004261 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004262 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004263 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4264 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4265 const xmlChar *fixed;
4266
4267 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4268 if (fixed != NULL) {
4269 if (xmlStrEqual(fixed, BAD_CAST "true"))
4270 facet->fixed = 1;
4271 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004272 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004273 child = node->children;
4274
4275 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004276 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4277 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004278 }
4279 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004280 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4281 "Facet %s has unexpected child content\n",
4282 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004283 }
4284 return (facet);
4285}
4286
4287/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004288 * xmlSchemaParseWildcardNs:
4289 * @ctxt: a schema parser context
4290 * @wildc: the wildcard, already created
4291 * @node: a subtree containing XML Schema informations
4292 *
4293 * Parses the attribute "processContents" and "namespace"
4294 * of a xsd:anyAttribute and xsd:any.
4295 * *WARNING* this interface is highly subject to change
4296 *
4297 * Returns 0 if everything goes fine, a positive error code
4298 * if something is not valid and -1 if an internal error occurs.
4299 */
4300static int
4301xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4302 xmlSchemaPtr schema,
4303 xmlSchemaWildcardPtr wildc,
4304 xmlNodePtr node)
4305{
4306 const xmlChar *pc, *ns, *dictnsItem;
4307 int ret = 0;
4308 xmlChar *nsItem;
4309 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4310 xmlAttrPtr attr;
4311
4312 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4313 if ((pc == NULL)
4314 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4315 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4316 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4317 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4318 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4319 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4320 } else {
4321 xmlSchemaPSimpleTypeErr(ctxt,
4322 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4323 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004324 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004325 NULL, NULL, NULL);
4326 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4327 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4328 }
4329 /*
4330 * Build the namespace constraints.
4331 */
4332 attr = xmlSchemaGetPropNode(node, "namespace");
4333 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4334 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4335 wildc->any = 1;
4336 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4337 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4338 if (wildc->negNsSet == NULL) {
4339 return (-1);
4340 }
4341 wildc->negNsSet->value = schema->targetNamespace;
4342 } else {
4343 const xmlChar *end, *cur;
4344
4345 cur = ns;
4346 do {
4347 while (IS_BLANK_CH(*cur))
4348 cur++;
4349 end = cur;
4350 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4351 end++;
4352 if (end == cur)
4353 break;
4354 nsItem = xmlStrndup(cur, end - cur);
4355 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4356 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4357 xmlSchemaPSimpleTypeErr(ctxt,
4358 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4359 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004360 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004361 "((##any | ##other) | List of (anyURI | "
4362 "(##targetNamespace | ##local)))",
4363 nsItem, NULL, NULL, NULL);
4364 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4365 } else {
4366 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4367 dictnsItem = schema->targetNamespace;
4368 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4369 dictnsItem = NULL;
4370 } else {
4371 /*
4372 * Validate the item (anyURI).
4373 */
4374 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4375 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4376 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4377 }
4378 /*
4379 * Avoid dublicate namespaces.
4380 */
4381 tmp = wildc->nsSet;
4382 while (tmp != NULL) {
4383 if (dictnsItem == tmp->value)
4384 break;
4385 tmp = tmp->next;
4386 }
4387 if (tmp == NULL) {
4388 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4389 if (tmp == NULL) {
4390 xmlFree(nsItem);
4391 return (-1);
4392 }
4393 tmp->value = dictnsItem;
4394 tmp->next = NULL;
4395 if (wildc->nsSet == NULL)
4396 wildc->nsSet = tmp;
4397 else
4398 lastNs->next = tmp;
4399 lastNs = tmp;
4400 }
4401
4402 }
4403 xmlFree(nsItem);
4404 cur = end;
4405 } while (*cur != 0);
4406 }
4407 return (ret);
4408}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004409
4410static int
4411xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4412 xmlSchemaTypePtr item,
4413 xmlNodePtr node,
4414 int minOccurs,
4415 int maxOccurs) {
4416
4417 if (maxOccurs != UNBOUNDED) {
4418 /*
4419 * TODO: Maby we should better not create the particle,
4420 * if min/max is invalid, since it could confuse the build of the
4421 * content model.
4422 */
4423 /*
4424 * 3.9.6 Schema Component Constraint: Particle Correct
4425 *
4426 */
4427 if (maxOccurs < 1) {
4428 /*
4429 * 2.2 {max occurs} must be greater than or equal to 1.
4430 */
4431 xmlSchemaPCustomAttrErr(ctxt,
4432 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4433 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4434 "The value must be greater than or equal to 1");
4435 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4436 } else if (minOccurs > maxOccurs) {
4437 /*
4438 * 2.1 {min occurs} must not be greater than {max occurs}.
4439 */
4440 xmlSchemaPCustomAttrErr(ctxt,
4441 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4442 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4443 "The value must not be greater than the value of 'maxOccurs'");
4444 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4445 }
4446 }
4447 return (0);
4448}
4449
Daniel Veillardc0826a72004-08-10 14:17:33 +00004450/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004451 * xmlSchemaParseAny:
4452 * @ctxt: a schema validation context
4453 * @schema: the schema being built
4454 * @node: a subtree containing XML Schema informations
4455 *
4456 * parse a XML schema Any declaration
4457 * *WARNING* this interface is highly subject to change
4458 *
4459 * Returns the new type structure or NULL in case of error
4460 */
4461static xmlSchemaTypePtr
4462xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4463 xmlNodePtr node)
4464{
4465 xmlSchemaTypePtr type;
4466 xmlNodePtr child = NULL;
4467 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004468 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004469 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004470
4471 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4472 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004473 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4474 "(nonNegativeInteger | unbounded)");
4475 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4476 "nonNegativeInteger");
4477 if ((minOccurs == 0) && (maxOccurs == 0))
4478 return (NULL);
4479
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004480 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004481 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004482 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004483 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004485 type->type = XML_SCHEMA_TYPE_ANY;
4486
Daniel Veillardc0826a72004-08-10 14:17:33 +00004487 wildc = xmlSchemaAddWildcard(ctxt);
4488 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004489 * Check min/max sanity.
4490 */
4491 type->maxOccurs = maxOccurs;
4492 type->minOccurs = minOccurs;
4493 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4494 node, type->minOccurs, type->maxOccurs);
4495 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004496 * This is not nice, since it is won't be used as a attribute wildcard,
4497 * but better than adding a field to the structure.
4498 */
4499 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004500 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004501 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4504 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 }
4506 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004507 xmlSchemaPErr2(ctxt, node, child,
4508 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4509 "Sequence %s has unexpected content\n", type->name,
4510 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004511 }
4512
4513 return (type);
4514}
4515
4516/**
4517 * xmlSchemaParseNotation:
4518 * @ctxt: a schema validation context
4519 * @schema: the schema being built
4520 * @node: a subtree containing XML Schema informations
4521 *
4522 * parse a XML schema Notation declaration
4523 *
4524 * Returns the new structure or NULL in case of error
4525 */
4526static xmlSchemaNotationPtr
4527xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004528 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004529{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004530 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 xmlSchemaNotationPtr ret;
4532 xmlNodePtr child = NULL;
4533
4534 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4535 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004536 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004538 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4539 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 return (NULL);
4541 }
4542 ret = xmlSchemaAddNotation(ctxt, schema, name);
4543 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004544 return (NULL);
4545 }
4546 child = node->children;
4547 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004548 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4549 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 }
4551 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004552 xmlSchemaPErr2(ctxt, node, child,
4553 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4554 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004555 }
4556
4557 return (ret);
4558}
4559
4560/**
4561 * xmlSchemaParseAnyAttribute:
4562 * @ctxt: a schema validation context
4563 * @schema: the schema being built
4564 * @node: a subtree containing XML Schema informations
4565 *
4566 * parse a XML schema AnyAttrribute declaration
4567 * *WARNING* this interface is highly subject to change
4568 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004569 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004570 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004571static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004572xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4573 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004574{
Daniel Veillard3646d642004-06-02 19:19:14 +00004575 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004576 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004577 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004578
4579 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4580 return (NULL);
4581
Daniel Veillard3646d642004-06-02 19:19:14 +00004582 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004583 if (ret == NULL) {
4584 return (NULL);
4585 }
William M. Bracke7091952004-05-11 15:09:58 +00004586 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004587 /*
4588 * Check for illegal attributes.
4589 */
4590 attr = node->properties;
4591 while (attr != NULL) {
4592 if (attr->ns == NULL) {
4593 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4594 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4595 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4596 xmlSchemaPIllegalAttrErr(ctxt,
4597 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4598 NULL, NULL, attr);
4599 }
4600 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4601 xmlSchemaPIllegalAttrErr(ctxt,
4602 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4603 NULL, NULL, attr);
4604 }
4605 attr = attr->next;
4606 }
4607 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4608 /*
4609 * Parse the namespace list.
4610 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004611 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4612 xmlSchemaFreeWildcard(ret);
4613 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004614 }
4615 /*
4616 * And now for the children...
4617 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004618 child = node->children;
4619 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004620 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4621 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004622 }
4623 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004624 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004625 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4626 NULL, NULL, node, child,
4627 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004628 }
4629
4630 return (ret);
4631}
4632
4633
4634/**
4635 * xmlSchemaParseAttribute:
4636 * @ctxt: a schema validation context
4637 * @schema: the schema being built
4638 * @node: a subtree containing XML Schema informations
4639 *
4640 * parse a XML schema Attrribute declaration
4641 * *WARNING* this interface is highly subject to change
4642 *
William M. Bracke7091952004-05-11 15:09:58 +00004643 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004644 */
4645static xmlSchemaAttributePtr
4646xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004647 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004648{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004649 const xmlChar *name, *attrValue;
4650 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004651 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004652 xmlNodePtr child = NULL;
4653 xmlAttrPtr attr, nameAttr;
4654 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004655
4656 /*
4657 * Note that the w3c spec assumes the schema to be validated with schema
4658 * for schemas beforehand.
4659 *
4660 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004661 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004662
4663 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4664 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004665 attr = xmlSchemaGetPropNode(node, "ref");
4666 nameAttr = xmlSchemaGetPropNode(node, "name");
4667
4668 if ((attr == NULL) && (nameAttr == NULL)) {
4669 /*
4670 * 3.2.3 : 3.1
4671 * One of ref or name must be present, but not both
4672 */
4673 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4674 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4675 "One of the attributes 'ref' or 'name' must be present");
4676 return (NULL);
4677 }
4678 if ((topLevel) || (attr == NULL)) {
4679 if (nameAttr == NULL) {
4680 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4681 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4682 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004684 }
4685 } else
4686 isRef = 1;
4687
4688 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004689 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004690 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4691
4692 /*
4693 * Parse as attribute reference.
4694 */
4695 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4696 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4697 &refPrefix, &ref) != 0) {
4698 return (NULL);
4699 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004700 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004701 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004702 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004703 if (ret == NULL) {
4704 if (repName != NULL)
4705 xmlFree(repName);
4706 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004707 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004708 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4709 ret->node = node;
4710 ret->refNs = refNs;
4711 ret->refPrefix = refPrefix;
4712 ret->ref = ref;
4713 /*
4714 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4715 */
4716 if (nameAttr != NULL)
4717 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4718 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4719 "ref", "name");
4720 /*
4721 * Check for illegal attributes.
4722 */
4723 attr = node->properties;
4724 while (attr != NULL) {
4725 if (attr->ns == NULL) {
4726 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4727 xmlStrEqual(attr->name, BAD_CAST "form")) {
4728 /*
4729 * 3.2.3 : 3.2
4730 * If ref is present, then all of <simpleType>,
4731 * form and type must be absent.
4732 */
4733 xmlSchemaPIllegalAttrErr(ctxt,
4734 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4735 (xmlSchemaTypePtr) ret, attr);
4736 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4737 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4738 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4739 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4740 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4741 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4742 xmlSchemaPIllegalAttrErr(ctxt,
4743 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4744 &repName, (xmlSchemaTypePtr) ret, attr);
4745 }
4746 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4747 xmlSchemaPIllegalAttrErr(ctxt,
4748 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4749 &repName, (xmlSchemaTypePtr) ret, attr);
4750 }
4751 attr = attr->next;
4752 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004753 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004754 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004755
4756 /*
4757 * Parse as attribute declaration.
4758 */
4759 if (xmlSchemaPValAttrNode(ctxt,
4760 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4761 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4762 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004763 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004764 /*
4765 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4766 */
4767 /*
4768 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4769 */
4770 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4771 xmlSchemaPSimpleTypeErr(ctxt,
4772 XML_SCHEMAP_NO_XMLNS,
4773 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004774 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004775 "The value must not match 'xmlns'",
4776 NULL, NULL);
4777 if (repName != NULL)
4778 xmlFree(repName);
4779 return (NULL);
4780 }
4781 /*
4782 * Evaluate the target namespace
4783 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004784 if (topLevel) {
4785 ns = schema->targetNamespace;
4786 } else {
4787 attr = xmlSchemaGetPropNode(node, "form");
4788 if (attr != NULL) {
4789 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4790 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4791 ns = schema->targetNamespace;
4792 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4793 xmlSchemaPSimpleTypeErr(ctxt,
4794 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4795 &repName, NULL, (xmlNodePtr) attr,
4796 NULL, "(qualified | unqualified)",
4797 attrValue, NULL, NULL, NULL);
4798 }
4799 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4800 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004801 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004802 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004803 if (ret == NULL) {
4804 if (repName != NULL)
4805 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004806 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004807 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004808 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4809 ret->node = node;
4810 if (topLevel)
4811 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4812 /*
4813 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4814 */
4815 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4816 xmlSchemaPCustomErr(ctxt,
4817 XML_SCHEMAP_NO_XSI,
4818 &repName, (xmlSchemaTypePtr) ret, node,
4819 "The target namespace must not match '%s'",
4820 xmlSchemaInstanceNs);
4821 }
4822 /*
4823 * Check for illegal attributes.
4824 */
4825 attr = node->properties;
4826 while (attr != NULL) {
4827 if (attr->ns == NULL) {
4828 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4829 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4830 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4831 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4832 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4833 if ((topLevel) ||
4834 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4835 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4836 xmlSchemaPIllegalAttrErr(ctxt,
4837 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4838 &repName, (xmlSchemaTypePtr) ret, attr);
4839 }
4840 }
4841 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4842 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4843 &repName, (xmlSchemaTypePtr) ret, attr);
4844 }
4845 attr = attr->next;
4846 }
4847 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4848 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004849 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004850 /* TODO: Check ID. */
4851 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004852 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004853 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004854 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004855 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4856 if (ret->defValue != NULL)
4857 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4858 /*
4859 * Attribute "default".
4860 */
4861 attr = xmlSchemaGetPropNode(node, "default");
4862 if (attr != NULL) {
4863 /*
4864 * 3.2.3 : 1
4865 * default and fixed must not both be present.
4866 */
4867 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4868 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4869 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4870 } else
4871 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4872 }
4873 if (topLevel == 0) {
4874 /*
4875 * Attribute "use".
4876 */
4877 attr = xmlSchemaGetPropNode(node, "use");
4878 if (attr != NULL) {
4879 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4880 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4881 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4882 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4883 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4884 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4885 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4886 else
4887 xmlSchemaPSimpleTypeErr(ctxt,
4888 XML_SCHEMAP_INVALID_ATTR_USE,
4889 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004890 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004891 attrValue, NULL, NULL, NULL);
4892 } else
4893 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4894 /*
4895 * 3.2.3 : 2
4896 * If default and use are both present, use must have
4897 * the actual value optional.
4898 */
4899 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4900 (ret->defValue != NULL) &&
4901 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4902 xmlSchemaPSimpleTypeErr(ctxt,
4903 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4904 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004905 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004906 "The value must be 'optional' if the attribute "
4907 "'default' is present as well", NULL, NULL);
4908 }
4909 }
4910 /*
4911 * And now for the children...
4912 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004913 child = node->children;
4914 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4916 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004917 }
4918 if (isRef) {
4919 if (child != NULL) {
4920 if (IS_SCHEMA(child, "simpleType"))
4921 /*
4922 * 3.2.3 : 3.2
4923 * If ref is present, then all of <simpleType>,
4924 * form and type must be absent.
4925 */
4926 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4927 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4928 "(annotation?)");
4929 else
4930 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4931 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4932 "(annotation?)");
4933 }
4934 } else {
4935 if (IS_SCHEMA(child, "simpleType")) {
4936 if (ret->typeName != NULL) {
4937 /*
4938 * 3.2.3 : 4
4939 * type and <simpleType> must not both be present.
4940 */
4941 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4942 &repName, (xmlSchemaTypePtr) ret, node, child,
4943 "The attribute 'type' and the <simpleType> child "
4944 "are mutually exclusive", NULL);
4945 } else
4946 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4947 child = child->next;
4948 }
4949 if (child != NULL)
4950 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4951 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4952 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004953 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004954 /*
4955 * Cleanup.
4956 */
4957 if (repName != NULL)
4958 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004959 return (ret);
4960}
4961
4962/**
4963 * xmlSchemaParseAttributeGroup:
4964 * @ctxt: a schema validation context
4965 * @schema: the schema being built
4966 * @node: a subtree containing XML Schema informations
4967 *
4968 * parse a XML schema Attribute Group declaration
4969 * *WARNING* this interface is highly subject to change
4970 *
4971 * Returns the attribute group or NULL in case of error.
4972 */
4973static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004974xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004975 xmlSchemaPtr schema, xmlNodePtr node,
4976 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004977{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004978 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004979 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004980 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004981 const xmlChar *oldcontainer;
4982 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004983
4984 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4985 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004986
4987 nameAttr = xmlSchemaGetPropNode(node, "name");
4988 attr = xmlSchemaGetPropNode(node, "ref");
4989 if ((topLevel) || (attr == NULL)) {
4990 /*
4991 * Parse as an attribute group definition.
4992 * Note that those are allowed at top level only.
4993 */
4994 if (nameAttr == NULL) {
4995 xmlSchemaPMissingAttrErr(ctxt,
4996 XML_SCHEMAP_S4S_ATTR_MISSING,
4997 NULL, NULL, node, "name", NULL);
4998 return (NULL);
4999 }
5000 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5001 /*
5002 * The name is crucial, exit if invalid.
5003 */
5004 if (xmlSchemaPValAttrNode(ctxt,
5005 NULL, NULL, nameAttr,
5006 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5007 return (NULL);
5008 }
5009 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5010 if (ret == NULL)
5011 return (NULL);
5012 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5013 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5014 ret->node = node;
5015 } else {
5016 char buf[50];
5017 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5018
5019 /*
5020 * Parse as an attribute group definition reference.
5021 */
5022 if (attr == NULL) {
5023 xmlSchemaPMissingAttrErr(ctxt,
5024 XML_SCHEMAP_S4S_ATTR_MISSING,
5025 NULL, NULL, node, "ref", NULL);
5026 }
5027 xmlSchemaPValAttrNodeQName(ctxt, schema,
5028 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5029
5030 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5031 name = (const xmlChar *) buf;
5032 if (name == NULL) {
5033 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5034 "attribute group definition reference", node);
5035 return (NULL);
5036 }
5037 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5038 if (ret == NULL)
5039 return (NULL);
5040 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5041 ret->ref = ref;
5042 ret->refNs = refNs;
5043 /* TODO: Is @refPrefix currently used? */
5044 ret->refPrefix = refPrefix;
5045 ret->node = node;
5046 }
5047 /*
5048 * Check for illegal attributes.
5049 */
5050 attr = node->properties;
5051 while (attr != NULL) {
5052 if (attr->ns == NULL) {
5053 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5054 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5055 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5056 {
5057 xmlSchemaPIllegalAttrErr(ctxt,
5058 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5059 NULL, NULL, attr);
5060 }
5061 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5062 xmlSchemaPIllegalAttrErr(ctxt,
5063 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5064 NULL, NULL, attr);
5065 }
5066 attr = attr->next;
5067 }
5068 /* TODO: Validate "id" ? */
5069 /*
5070 * And now for the children...
5071 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005072 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005073 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005074 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005075 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005076 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5077 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005078 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005079 if (topLevel) {
5080 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5081 if (IS_SCHEMA(child, "anyAttribute")) {
5082 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5083 child = child->next;
5084 }
5085 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005086 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005087 xmlSchemaPContentErr(ctxt,
5088 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5089 NULL, NULL, node, child, NULL,
5090 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005091 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005092 ctxt->container = oldcontainer;
5093 return (ret);
5094}
5095
5096/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005097 * xmlSchemaPValAttrFormDefault:
5098 * @value: the value
5099 * @flags: the flags to be modified
5100 * @flagQualified: the specific flag for "qualified"
5101 *
5102 * Returns 0 if the value is valid, 1 otherwise.
5103 */
5104static int
5105xmlSchemaPValAttrFormDefault(const xmlChar *value,
5106 int *flags,
5107 int flagQualified)
5108{
5109 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5110 if ((*flags & flagQualified) == 0)
5111 *flags |= flagQualified;
5112 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5113 return (1);
5114
5115 return (0);
5116}
5117
5118/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005119 * xmlSchemaPValAttrBlockFinal:
5120 * @value: the value
5121 * @flags: the flags to be modified
5122 * @flagAll: the specific flag for "#all"
5123 * @flagExtension: the specific flag for "extension"
5124 * @flagRestriction: the specific flag for "restriction"
5125 * @flagSubstitution: the specific flag for "substitution"
5126 * @flagList: the specific flag for "list"
5127 * @flagUnion: the specific flag for "union"
5128 *
5129 * Validates the value of the attribute "final" and "block". The value
5130 * is converted into the specified flag values and returned in @flags.
5131 *
5132 * Returns 0 if the value is valid, 1 otherwise.
5133 */
5134
5135static int
5136xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5137 int *flags,
5138 int flagAll,
5139 int flagExtension,
5140 int flagRestriction,
5141 int flagSubstitution,
5142 int flagList,
5143 int flagUnion)
5144{
5145 int ret = 0;
5146
5147 /*
5148 * TODO: This does not check for dublicate entries.
5149 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005150 if (value == NULL)
5151 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005152 if (xmlStrEqual(value, BAD_CAST "#all")) {
5153 if (flagAll != -1)
5154 *flags |= flagAll;
5155 else {
5156 if (flagExtension != -1)
5157 *flags |= flagExtension;
5158 if (flagRestriction != -1)
5159 *flags |= flagRestriction;
5160 if (flagSubstitution != -1)
5161 *flags |= flagSubstitution;
5162 if (flagList != -1)
5163 *flags |= flagList;
5164 if (flagUnion != -1)
5165 *flags |= flagUnion;
5166 }
5167 } else {
5168 const xmlChar *end, *cur = value;
5169 xmlChar *item;
5170
5171 do {
5172 while (IS_BLANK_CH(*cur))
5173 cur++;
5174 end = cur;
5175 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5176 end++;
5177 if (end == cur)
5178 break;
5179 item = xmlStrndup(cur, end - cur);
5180 if (xmlStrEqual(item, BAD_CAST "extension")) {
5181 if (flagExtension != -1) {
5182 if ((*flags & flagExtension) == 0)
5183 *flags |= flagExtension;
5184 } else
5185 ret = 1;
5186 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5187 if (flagRestriction != -1) {
5188 if ((*flags & flagRestriction) == 0)
5189 *flags |= flagRestriction;
5190 } else
5191 ret = 1;
5192 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5193 if (flagSubstitution != -1) {
5194 if ((*flags & flagSubstitution) == 0)
5195 *flags |= flagSubstitution;
5196 } else
5197 ret = 1;
5198 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5199 if (flagList != -1) {
5200 if ((*flags & flagList) == 0)
5201 *flags |= flagList;
5202 } else
5203 ret = 1;
5204 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5205 if (flagUnion != -1) {
5206 if ((*flags & flagUnion) == 0)
5207 *flags |= flagUnion;
5208 } else
5209 ret = 1;
5210 } else
5211 ret = 1;
5212 if (item != NULL)
5213 xmlFree(item);
5214 cur = end;
5215 } while ((ret == 0) && (*cur != 0));
5216 }
5217
5218 return (ret);
5219}
5220
5221/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005222 * xmlSchemaParseElement:
5223 * @ctxt: a schema validation context
5224 * @schema: the schema being built
5225 * @node: a subtree containing XML Schema informations
5226 *
5227 * parse a XML schema Element declaration
5228 * *WARNING* this interface is highly subject to change
5229 *
William M. Bracke7091952004-05-11 15:09:58 +00005230 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005231 */
5232static xmlSchemaElementPtr
5233xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005234 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005235{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005236 const xmlChar *name = NULL;
5237 const xmlChar *attrValue;
5238 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005239 xmlSchemaElementPtr ret;
5240 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005241 const xmlChar *oldcontainer;
5242 xmlAttrPtr attr, nameAttr;
5243 int minOccurs, maxOccurs;
5244 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005245
5246 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5247 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005248
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5250 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005251
Daniel Veillardc0826a72004-08-10 14:17:33 +00005252 oldcontainer = ctxt->container;
5253
5254 nameAttr = xmlSchemaGetPropNode(node, "name");
5255 attr = xmlSchemaGetPropNode(node, "ref");
5256 if ((topLevel) || (attr == NULL)) {
5257 if (nameAttr == NULL) {
5258 xmlSchemaPMissingAttrErr(ctxt,
5259 XML_SCHEMAP_S4S_ATTR_MISSING,
5260 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5261 "name", NULL);
5262 return (NULL);
5263 }
5264 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5265 } else {
5266 isRef = 1;
5267
5268 }
5269 /*
5270 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5271 * to no component at all
5272 * TODO: It might be better to validate the element, even if it won't be
5273 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005274 */
5275 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5276 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005277 if ((minOccurs == 0) && (maxOccurs == 0))
5278 return (NULL);
5279 /*
5280 * If we get a "ref" attribute on a local <element> we will assume it's
5281 * a reference - even if there's a "name" attribute; this seems to be more
5282 * robust.
5283 */
5284 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005285 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005286 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5287
5288 /*
5289 * Parse as a particle.
5290 */
5291 xmlSchemaPValAttrNodeQName(ctxt, schema,
5292 (xmlChar **) &xmlSchemaElemDesAttrRef,
5293 NULL, attr, &refNs, &refPrefix, &ref);
5294
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005295 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005296 name = (const xmlChar *) buf;
5297 ret = xmlSchemaAddElement(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005298 if (ret == NULL) {
5299 if (repName != NULL)
5300 xmlFree(repName);
5301 return (NULL);
5302 }
5303 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5304 ret->node = node;
5305 ret->ref = ref;
5306 ret->refNs = refNs;
5307 ret->refPrefix = refPrefix;
5308 ret->flags |= XML_SCHEMAS_ELEM_REF;
5309 /*
5310 * Check for illegal attributes.
5311 */
5312 /*
5313 * 3.3.3 : 2.1
5314 * One of ref or name must be present, but not both
5315 */
5316 if (nameAttr != NULL) {
5317 xmlSchemaPMutualExclAttrErr(ctxt,
5318 XML_SCHEMAP_SRC_ELEMENT_2_1,
5319 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5320 "ref", "name");
5321 }
5322 /* 3.3.3 : 2.2 */
5323 attr = node->properties;
5324 while (attr != NULL) {
5325 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005326 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5327 xmlStrEqual(attr->name, BAD_CAST "name") ||
5328 xmlStrEqual(attr->name, BAD_CAST "id") ||
5329 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5330 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5331 {
5332 attr = attr->next;
5333 continue;
5334 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005335 xmlSchemaPCustomAttrErr(ctxt,
5336 XML_SCHEMAP_SRC_ELEMENT_2_2,
5337 &repName, (xmlSchemaTypePtr) ret, attr,
5338 "Only the attributes 'minOccurs', 'maxOccurs' and "
5339 "'id' are allowed in addition to 'ref'");
5340 break;
5341 }
5342 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5343 xmlSchemaPIllegalAttrErr(ctxt,
5344 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5345 &repName, (xmlSchemaTypePtr) ret, attr);
5346 }
5347 attr = attr->next;
5348 }
5349 } else {
5350 const xmlChar *ns = NULL, *fixed;
5351
5352 /*
5353 * Parse as an element declaration.
5354 */
5355 if (xmlSchemaPValAttrNode(ctxt,
5356 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5357 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5358 return (NULL);
5359 /*
5360 * Evaluate the target namespace.
5361 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005362 if (topLevel) {
5363 ns = schema->targetNamespace;
5364 } else {
5365 attr = xmlSchemaGetPropNode(node, "form");
5366 if (attr != NULL) {
5367 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5368 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005369 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005370 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5371 xmlSchemaPSimpleTypeErr(ctxt,
5372 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5373 &repName, NULL, (xmlNodePtr) attr,
5374 NULL, "(qualified | unqualified)",
5375 attrValue, NULL, NULL, NULL);
5376 }
5377 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5378 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005379 }
5380 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005381 if (ret == NULL) {
5382 if (repName != NULL)
5383 xmlFree(repName);
5384 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005385 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005386 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5387 ret->node = node;
5388 /*
5389 * Check for illegal attributes.
5390 */
William M. Bracke7091952004-05-11 15:09:58 +00005391 attr = node->properties;
5392 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005393 if (attr->ns == NULL) {
5394 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5395 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5396 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5397 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5398 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5399 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005400 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5401 {
5402 if (topLevel == 0) {
5403 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005404 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005405 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5406 {
5407 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5408 /*
5409 * 3.3.6 : 3 If there is a non-·absent· {substitution
5410 * group affiliation}, then {scope} must be global.
5411 * TODO: This one is redundant, since the S4S does
5412 * prohibit this attribute on local declarations already;
5413 * so why an explicit error code? Weird spec.
5414 * TODO: Move this to the proper constraint layer.
5415 * TODO: Or better wait for spec 1.1 to come.
5416 */
5417 xmlSchemaPIllegalAttrErr(ctxt,
5418 XML_SCHEMAP_E_PROPS_CORRECT_3,
5419 &repName, (xmlSchemaTypePtr) ret, attr);
5420 } else {
5421 xmlSchemaPIllegalAttrErr(ctxt,
5422 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5423 &repName, (xmlSchemaTypePtr) ret, attr);
5424 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005425 }
5426 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5427 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5428 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5429
5430 xmlSchemaPIllegalAttrErr(ctxt,
5431 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5432 &repName, (xmlSchemaTypePtr) ret, attr);
5433 }
5434 }
5435 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5436
5437 xmlSchemaPIllegalAttrErr(ctxt,
5438 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5439 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005440 }
5441 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005442 }
William M. Bracke7091952004-05-11 15:09:58 +00005443 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005444 * Extract/validate attributes.
5445 */
5446 if (topLevel) {
5447 /*
5448 * Process top attributes of global element declarations here.
5449 */
5450 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5451 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5452 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5453 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5454 &(ret->substGroupNs), NULL, &(ret->substGroup));
5455 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5456 node, "abstract", 0))
5457 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5458 /*
5459 * Attribute "final".
5460 */
5461 attr = xmlSchemaGetPropNode(node, "final");
5462 if (attr == NULL) {
5463 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5464 } else {
5465 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5466 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5467 -1,
5468 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5469 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5470 xmlSchemaPSimpleTypeErr(ctxt,
5471 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5472 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005473 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005474 attrValue, NULL, NULL, NULL);
5475 }
5476 }
5477 }
5478 /*
5479 * Attribute "block".
5480 */
5481 attr = xmlSchemaGetPropNode(node, "block");
5482 if (attr == NULL) {
5483 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5484 } else {
5485 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5486 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5487 -1,
5488 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5489 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5490 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5491 xmlSchemaPSimpleTypeErr(ctxt,
5492 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5493 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005494 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005495 "restriction | substitution))", attrValue,
5496 NULL, NULL, NULL);
5497 }
5498 }
5499 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5500 node, "nillable", 0))
5501 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005502
Daniel Veillardc0826a72004-08-10 14:17:33 +00005503 xmlSchemaPValAttrQName(ctxt, schema,
5504 &repName, (xmlSchemaTypePtr) ret, node,
5505 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005506
Daniel Veillardc0826a72004-08-10 14:17:33 +00005507 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5508 attr = xmlSchemaGetPropNode(node, "fixed");
5509 if (attr != NULL) {
5510 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5511 if (ret->value != NULL) {
5512 /*
5513 * 3.3.3 : 1
5514 * default and fixed must not both be present.
5515 */
5516 xmlSchemaPMutualExclAttrErr(ctxt,
5517 XML_SCHEMAP_SRC_ELEMENT_1,
5518 &repName, (xmlSchemaTypePtr) ret, attr,
5519 "default", "fixed");
5520 } else {
5521 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5522 ret->value = fixed;
5523 }
5524 }
5525 }
5526 /*
5527 * Extract/validate common attributes.
5528 */
5529 /* TODO: Check ID: */
5530 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5531 ret->minOccurs = minOccurs;
5532 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005533 if (topLevel != 1)
5534 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5535 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005536 /*
5537 * And now for the children...
5538 */
5539 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005540 child = node->children;
5541 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5543 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005544 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005545 if (isRef) {
5546 if (child != NULL) {
5547 xmlSchemaPContentErr(ctxt,
5548 XML_SCHEMAP_SRC_ELEMENT_2_2,
5549 &repName, (xmlSchemaTypePtr) ret, node, child,
5550 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005551 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005552 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005553 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 /*
5555 * 3.3.3 : 3
5556 * "type" and either <simpleType> or <complexType> are mutually
5557 * exclusive
5558 */
William M. Bracke7091952004-05-11 15:09:58 +00005559 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005560 xmlSchemaPContentErr(ctxt,
5561 XML_SCHEMAP_SRC_ELEMENT_3,
5562 &repName, (xmlSchemaTypePtr) ret, node, child,
5563 "The attribute 'type' and the <complexType> child are "
5564 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005565 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005566 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005567 child = child->next;
5568 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005569 /*
5570 * 3.3.3 : 3
5571 * "type" and either <simpleType> or <complexType> are
5572 * mutually exclusive
5573 */
William M. Bracke7091952004-05-11 15:09:58 +00005574 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005575 xmlSchemaPContentErr(ctxt,
5576 XML_SCHEMAP_SRC_ELEMENT_3,
5577 &repName, (xmlSchemaTypePtr) ret, node, child,
5578 "The attribute 'type' and the <simpleType> child are "
5579 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005580 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005581 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005582 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005583 }
William M. Bracke7091952004-05-11 15:09:58 +00005584 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005585 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005586 TODO child = child->next;
5587 }
5588 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005589 xmlSchemaPContentErr(ctxt,
5590 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5591 &repName, (xmlSchemaTypePtr) ret, node, child,
5592 NULL, "(annotation?, ((simpleType | complexType)?, "
5593 "(unique | key | keyref)*))");
5594 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005595
Daniel Veillardc0826a72004-08-10 14:17:33 +00005596 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005597 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005598 /*
5599 * Cleanup.
5600 */
5601 if (repName != NULL)
5602 xmlFree(repName);
5603 /*
5604 * NOTE: Element Declaration Representation OK 4. will be checked at a
5605 * different layer.
5606 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005607 return (ret);
5608}
5609
5610/**
5611 * xmlSchemaParseUnion:
5612 * @ctxt: a schema validation context
5613 * @schema: the schema being built
5614 * @node: a subtree containing XML Schema informations
5615 *
5616 * parse a XML schema Union definition
5617 * *WARNING* this interface is highly subject to change
5618 *
William M. Bracke7091952004-05-11 15:09:58 +00005619 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005620 * 1 in case of success.
5621 */
5622static xmlSchemaTypePtr
5623xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005624 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005625{
5626 xmlSchemaTypePtr type, subtype, last = NULL;
5627 xmlNodePtr child = NULL;
5628 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005629 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005630
5631 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5632 return (NULL);
5633
William M. Brack2f2a6632004-08-20 23:09:47 +00005634 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5635 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005636 if (type == NULL)
5637 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005638 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005639 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005640 /*
5641 * Check for illegal attributes.
5642 */
5643 attr = node->properties;
5644 while (attr != NULL) {
5645 if (attr->ns == NULL) {
5646 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5647 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5648 xmlSchemaPIllegalAttrErr(ctxt,
5649 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5650 NULL, type, attr);
5651 }
5652 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5653 xmlSchemaPIllegalAttrErr(ctxt,
5654 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5655 NULL, type, attr);
5656 }
5657 attr = attr->next;
5658 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005659 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005660 /*
5661 * Attribute "memberTypes". This is a list of QNames.
5662 * TODO: Validate the QNames.
5663 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005664 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005665 /*
5666 * And now for the children...
5667 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005668 child = node->children;
5669 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005670 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5671 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005672 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005673 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005674 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005675 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005676 if (subtype != NULL) {
5677 if (last == NULL) {
5678 type->subtypes = subtype;
5679 last = subtype;
5680 } else {
5681 last->next = subtype;
5682 last = subtype;
5683 }
5684 last->next = NULL;
5685 }
5686 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005687 }
5688 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005689 /* TODO: Think about the error code. */
5690 xmlSchemaPContentErr(ctxt,
5691 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5692 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005693 }
5694 return (type);
5695}
5696
5697/**
5698 * xmlSchemaParseList:
5699 * @ctxt: a schema validation context
5700 * @schema: the schema being built
5701 * @node: a subtree containing XML Schema informations
5702 *
5703 * parse a XML schema List definition
5704 * *WARNING* this interface is highly subject to change
5705 *
William M. Bracke7091952004-05-11 15:09:58 +00005706 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005707 * 1 in case of success.
5708 */
5709static xmlSchemaTypePtr
5710xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005711 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005712{
5713 xmlSchemaTypePtr type, subtype;
5714 xmlNodePtr child = NULL;
5715 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005716 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005717
5718 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5719 return (NULL);
5720
William M. Brack2f2a6632004-08-20 23:09:47 +00005721 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5722 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005723 if (type == NULL)
5724 return (NULL);
5725 type->node = node;
5726 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005727 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005728 /*
5729 * Check for illegal attributes.
5730 */
5731 attr = node->properties;
5732 while (attr != NULL) {
5733 if (attr->ns == NULL) {
5734 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5735 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5736 xmlSchemaPIllegalAttrErr(ctxt,
5737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5738 NULL, type, attr);
5739 }
5740 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5741 xmlSchemaPIllegalAttrErr(ctxt,
5742 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5743 NULL, type, attr);
5744 }
5745 attr = attr->next;
5746 }
5747 /*
5748 * Attribute "itemType".
5749 */
5750 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5751 node, "itemType", &(type->baseNs), NULL, &(type->base));
5752 /*
5753 * And now for the children...
5754 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005755 child = node->children;
5756 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005757 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5758 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005759 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005760 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005761 if (IS_SCHEMA(child, "simpleType")) {
5762 if (type->base != NULL) {
5763 xmlSchemaPCustomErr(ctxt,
5764 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5765 NULL, type, node,
5766 "The attribute 'itemType' and the <simpleType> child "
5767 "are mutually exclusive", NULL);
5768 } else {
5769 subtype = (xmlSchemaTypePtr)
5770 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5771 type->subtypes = subtype;
5772 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005773 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005774 }
5775 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005776 /* TODO: Think about the error code. */
5777 xmlSchemaPContentErr(ctxt,
5778 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5779 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005780 }
5781 return (type);
5782}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005783
Daniel Veillard4255d502002-04-16 15:50:10 +00005784/**
5785 * xmlSchemaParseSimpleType:
5786 * @ctxt: a schema validation context
5787 * @schema: the schema being built
5788 * @node: a subtree containing XML Schema informations
5789 *
5790 * parse a XML schema Simple Type definition
5791 * *WARNING* this interface is highly subject to change
5792 *
William M. Bracke7091952004-05-11 15:09:58 +00005793 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005794 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005795 */
5796static xmlSchemaTypePtr
5797xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005798 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005799{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005800 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005801 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005802 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005803 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005804 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005805
5806 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5807 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005808
Daniel Veillardc0826a72004-08-10 14:17:33 +00005809 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005810 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005811 if (attr == NULL) {
5812 xmlSchemaPMissingAttrErr(ctxt,
5813 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005814 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 "name", NULL);
5816 return (NULL);
5817 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005818 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005819 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005820 return (NULL);
5821 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005822 }
5823
5824 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005825 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005826
Daniel Veillard01fa6152004-06-29 17:04:39 +00005827 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005828 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005829 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005830 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005831 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005832 if (type == NULL)
5833 return (NULL);
5834 type->node = node;
5835 type->type = XML_SCHEMA_TYPE_SIMPLE;
5836 /*
5837 * Check for illegal attributes.
5838 */
5839 attr = node->properties;
5840 while (attr != NULL) {
5841 if (attr->ns == NULL) {
5842 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5843 xmlSchemaPIllegalAttrErr(ctxt,
5844 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005845 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005846 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005847 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5848 xmlSchemaPIllegalAttrErr(ctxt,
5849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005850 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005851 }
5852 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005853 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005854 } else {
5855 /*
5856 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005857 *
5858 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005859 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005860 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005861 if (type == NULL)
5862 return (NULL);
5863 type->node = node;
5864 type->type = XML_SCHEMA_TYPE_SIMPLE;
5865 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5866 /*
5867 * Check for illegal attributes.
5868 */
5869 attr = node->properties;
5870 while (attr != NULL) {
5871 if (attr->ns == NULL) {
5872 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5873 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005874 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005875 xmlSchemaPIllegalAttrErr(ctxt,
5876 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005877 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005878 }
5879 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5880 xmlSchemaPIllegalAttrErr(ctxt,
5881 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005882 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005883 }
5884 attr = attr->next;
5885 }
5886 /*
5887 * Attribute "final".
5888 */
5889 attr = xmlSchemaGetPropNode(node, "final");
5890 if (attr == NULL) {
5891 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5892 } else {
5893 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5894 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5895 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5896 XML_SCHEMAS_TYPE_FINAL_LIST,
5897 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5898
5899 xmlSchemaPSimpleTypeErr(ctxt,
5900 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005901 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005902 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005903 attrValue, NULL, NULL, NULL);
5904 }
5905 }
5906 }
5907 /* TODO: Check id. */
5908 type->id = xmlSchemaGetProp(ctxt, node, "id");
5909 /*
5910 * And now for the children...
5911 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005912 oldCtxtType = ctxt->ctxtType;
5913 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005914 ctxt->ctxtType = type;
5915 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005916 child = node->children;
5917 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005918 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5919 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005920 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005921 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005922 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005923 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005924 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005925 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005926 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005927 subtype = (xmlSchemaTypePtr)
5928 xmlSchemaParseList(ctxt, schema, child);
5929 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005930 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005931 subtype = (xmlSchemaTypePtr)
5932 xmlSchemaParseUnion(ctxt, schema, child);
5933 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005934 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005935 type->subtypes = subtype;
5936 if ((child != NULL) || (subtype == NULL)) {
5937 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005938 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005939 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005940 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005941 ctxt->parentItem = oldParentItem;
5942 ctxt->ctxtType = oldCtxtType;
5943 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005944
Daniel Veillard4255d502002-04-16 15:50:10 +00005945 return (type);
5946}
5947
5948
5949/**
5950 * xmlSchemaParseGroup:
5951 * @ctxt: a schema validation context
5952 * @schema: the schema being built
5953 * @node: a subtree containing XML Schema informations
5954 *
5955 * parse a XML schema Group definition
5956 * *WARNING* this interface is highly subject to change
5957 *
William M. Bracke7091952004-05-11 15:09:58 +00005958 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005959 * 1 in case of success.
5960 */
5961static xmlSchemaTypePtr
5962xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005963 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005964{
5965 xmlSchemaTypePtr type, subtype;
5966 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005967 const xmlChar *name;
5968 const xmlChar *ref = NULL, *refNs = NULL;
5969 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005970 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005971
5972 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5973 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005974 /*
5975 * TODO: Validate the element even if no item is created
5976 * (i.e. min/maxOccurs == 0).
5977 */
5978 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5979 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
5980 if ((minOccurs == 0) && (maxOccurs == 0)) {
5981 return (NULL);
5982 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005983 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005984 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005985 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5986 if (ref == NULL) {
5987 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005988 XML_SCHEMAP_GROUP_NONAME_NOREF,
5989 "Group definition or particle: One of the attributes \"name\" "
5990 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005991 return (NULL);
5992 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005993 if (refNs == NULL)
5994 refNs = schema->targetNamespace;
5995 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5996 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005997 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005998 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 if (type == NULL)
6000 return (NULL);
6001 type->node = node;
6002 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00006003 if (topLevel)
6004 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006005 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006006 type->ref = ref;
6007 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006008 type->minOccurs = minOccurs;
6009 type->maxOccurs = maxOccurs;
6010 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006011 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006012
6013 child = node->children;
6014 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006015 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6016 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006017 }
6018 subtype = NULL;
6019 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006020 subtype = (xmlSchemaTypePtr)
6021 xmlSchemaParseAll(ctxt, schema, child);
6022 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006023 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006024 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6025 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006026 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006027 subtype = (xmlSchemaTypePtr)
6028 xmlSchemaParseSequence(ctxt, schema, child);
6029 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006030 }
6031 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006032 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006035 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006036 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006037 }
6038
6039 return (type);
6040}
6041
6042/**
6043 * xmlSchemaParseAll:
6044 * @ctxt: a schema validation context
6045 * @schema: the schema being built
6046 * @node: a subtree containing XML Schema informations
6047 *
6048 * parse a XML schema All definition
6049 * *WARNING* this interface is highly subject to change
6050 *
William M. Bracke7091952004-05-11 15:09:58 +00006051 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006052 * 1 in case of success.
6053 */
6054static xmlSchemaTypePtr
6055xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006056 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006057{
6058 xmlSchemaTypePtr type, subtype, last = NULL;
6059 xmlNodePtr child = NULL;
6060 xmlChar name[30];
6061
6062 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6063 return (NULL);
6064
6065
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006066 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006067 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006068 if (type == NULL)
6069 return (NULL);
6070 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006071 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006072 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006073
6074 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6075 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Daniel Veillard4255d502002-04-16 15:50:10 +00006076
6077 child = node->children;
6078 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006079 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6080 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006081 }
6082 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006083 subtype = (xmlSchemaTypePtr)
6084 xmlSchemaParseElement(ctxt, schema, child, 0);
6085 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006086 if (subtype->minOccurs > 1)
6087 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006088 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006089 NULL, NULL);
6090 if (subtype->maxOccurs > 1)
6091 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006092 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006093 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006094 if (last == NULL) {
6095 type->subtypes = subtype;
6096 last = subtype;
6097 } else {
6098 last->next = subtype;
6099 last = subtype;
6100 }
6101 last->next = NULL;
6102 }
6103 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006104 }
6105 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006106 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006107 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006108 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006109 }
6110
6111 return (type);
6112}
6113
6114/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006115 * xmlSchemaCleanupDoc:
6116 * @ctxt: a schema validation context
6117 * @node: the root of the document.
6118 *
6119 * removes unwanted nodes in a schemas document tree
6120 */
6121static void
6122xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6123{
6124 xmlNodePtr delete, cur;
6125
6126 if ((ctxt == NULL) || (root == NULL)) return;
6127
6128 /*
6129 * Remove all the blank text nodes
6130 */
6131 delete = NULL;
6132 cur = root;
6133 while (cur != NULL) {
6134 if (delete != NULL) {
6135 xmlUnlinkNode(delete);
6136 xmlFreeNode(delete);
6137 delete = NULL;
6138 }
6139 if (cur->type == XML_TEXT_NODE) {
6140 if (IS_BLANK_NODE(cur)) {
6141 if (xmlNodeGetSpacePreserve(cur) != 1) {
6142 delete = cur;
6143 }
6144 }
6145 } else if ((cur->type != XML_ELEMENT_NODE) &&
6146 (cur->type != XML_CDATA_SECTION_NODE)) {
6147 delete = cur;
6148 goto skip_children;
6149 }
6150
6151 /*
6152 * Skip to next node
6153 */
6154 if (cur->children != NULL) {
6155 if ((cur->children->type != XML_ENTITY_DECL) &&
6156 (cur->children->type != XML_ENTITY_REF_NODE) &&
6157 (cur->children->type != XML_ENTITY_NODE)) {
6158 cur = cur->children;
6159 continue;
6160 }
6161 }
6162 skip_children:
6163 if (cur->next != NULL) {
6164 cur = cur->next;
6165 continue;
6166 }
6167
6168 do {
6169 cur = cur->parent;
6170 if (cur == NULL)
6171 break;
6172 if (cur == root) {
6173 cur = NULL;
6174 break;
6175 }
6176 if (cur->next != NULL) {
6177 cur = cur->next;
6178 break;
6179 }
6180 } while (cur != NULL);
6181 }
6182 if (delete != NULL) {
6183 xmlUnlinkNode(delete);
6184 xmlFreeNode(delete);
6185 delete = NULL;
6186 }
6187}
6188
William M. Brack2f2a6632004-08-20 23:09:47 +00006189
6190/**
6191 * xmlSchemaImportSchema
6192 *
6193 * @ctxt: a schema validation context
6194 * @schemaLocation: an URI defining where to find the imported schema
6195 *
6196 * import a XML schema
6197 * *WARNING* this interface is highly subject to change
6198 *
6199 * Returns -1 in case of error and 1 in case of success.
6200 */
6201#if 0
6202static xmlSchemaImportPtr
6203xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6204 const xmlChar *schemaLocation)
6205{
6206 xmlSchemaImportPtr import;
6207 xmlSchemaParserCtxtPtr newctxt;
6208
6209 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6210 if (newctxt == NULL) {
6211 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6212 NULL);
6213 return (NULL);
6214 }
6215 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6216 /* Keep the same dictionnary for parsing, really */
6217 xmlDictReference(ctxt->dict);
6218 newctxt->dict = ctxt->dict;
6219 newctxt->includes = 0;
6220 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6221
6222 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6223 ctxt->userData);
6224
6225 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6226 if (import == NULL) {
6227 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6228 NULL);
6229 xmlSchemaFreeParserCtxt(newctxt);
6230 return (NULL);
6231 }
6232
6233 memset(import, 0, sizeof(xmlSchemaImport));
6234 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6235 import->schema = xmlSchemaParse(newctxt);
6236
6237 if (import->schema == NULL) {
6238 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006239 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006240 "Failed to import schema from location \"%s\".\n",
6241 schemaLocation, NULL);
6242
6243 xmlSchemaFreeParserCtxt(newctxt);
6244 /* The schemaLocation is held by the dictionary.
6245 if (import->schemaLocation != NULL)
6246 xmlFree((xmlChar *)import->schemaLocation);
6247 */
6248 xmlFree(import);
6249 return NULL;
6250 }
6251
6252 xmlSchemaFreeParserCtxt(newctxt);
6253 return import;
6254}
6255#endif
6256
6257static void
6258xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6259{
6260 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6261 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6262
6263 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6264 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6265
6266 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6267 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6268 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6269 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6270 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6271 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6272 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6273 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6274
6275 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6276 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6277 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6278 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6279 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6280 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6281}
6282
6283static void
6284xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6285 xmlSchemaPtr schema,
6286 xmlNodePtr node)
6287{
6288 xmlAttrPtr attr;
6289 const xmlChar *val;
6290
6291 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6292 if (attr != NULL) {
6293 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6294 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6295 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6296 xmlSchemaPSimpleTypeErr(ctxt,
6297 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6298 NULL, NULL, (xmlNodePtr) attr, NULL,
6299 "(qualified | unqualified)", val, NULL, NULL, NULL);
6300 }
6301 }
6302
6303 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6304 if (attr != NULL) {
6305 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6306 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6307 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6308 xmlSchemaPSimpleTypeErr(ctxt,
6309 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6310 NULL, NULL, (xmlNodePtr) attr, NULL,
6311 "(qualified | unqualified)", val, NULL, NULL, NULL);
6312 }
6313 }
6314
6315 attr = xmlSchemaGetPropNode(node, "finalDefault");
6316 if (attr != NULL) {
6317 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6318 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6319 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6320 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6321 -1,
6322 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6323 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6324 xmlSchemaPSimpleTypeErr(ctxt,
6325 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6326 NULL, NULL, (xmlNodePtr) attr, NULL,
6327 "(#all | List of (extension | restriction | list | union))",
6328 val, NULL, NULL, NULL);
6329 }
6330 }
6331
6332 attr = xmlSchemaGetPropNode(node, "blockDefault");
6333 if (attr != NULL) {
6334 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6335 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6336 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6337 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6338 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6339 xmlSchemaPSimpleTypeErr(ctxt,
6340 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6341 NULL, NULL, (xmlNodePtr) attr, NULL,
6342 "(#all | List of (extension | restriction | substitution))",
6343 val, NULL, NULL, NULL);
6344 }
6345 }
6346}
6347
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006348/**
6349 * xmlSchemaParseSchemaTopLevel:
6350 * @ctxt: a schema validation context
6351 * @schema: the schemas
6352 * @nodes: the list of top level nodes
6353 *
6354 * Returns the internal XML Schema structure built from the resource or
6355 * NULL in case of error
6356 */
6357static void
6358xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6359 xmlSchemaPtr schema, xmlNodePtr nodes)
6360{
6361 xmlNodePtr child;
6362 xmlSchemaAnnotPtr annot;
6363
6364 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6365 return;
6366
6367 child = nodes;
6368 while ((IS_SCHEMA(child, "include")) ||
6369 (IS_SCHEMA(child, "import")) ||
6370 (IS_SCHEMA(child, "redefine")) ||
6371 (IS_SCHEMA(child, "annotation"))) {
6372 if (IS_SCHEMA(child, "annotation")) {
6373 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6374 if (schema->annot == NULL)
6375 schema->annot = annot;
6376 else
6377 xmlSchemaFreeAnnot(annot);
6378 } else if (IS_SCHEMA(child, "import")) {
6379 xmlSchemaParseImport(ctxt, schema, child);
6380 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006381 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006382 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006383 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006384 } else if (IS_SCHEMA(child, "redefine")) {
6385 TODO
6386 }
6387 child = child->next;
6388 }
6389 while (child != NULL) {
6390 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006391 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006392 child = child->next;
6393 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006394 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006395 child = child->next;
6396 } else if (IS_SCHEMA(child, "element")) {
6397 xmlSchemaParseElement(ctxt, schema, child, 1);
6398 child = child->next;
6399 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006400 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006401 child = child->next;
6402 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006403 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006404 child = child->next;
6405 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006406 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006407 child = child->next;
6408 } else if (IS_SCHEMA(child, "notation")) {
6409 xmlSchemaParseNotation(ctxt, schema, child);
6410 child = child->next;
6411 } else {
6412 xmlSchemaPErr2(ctxt, NULL, child,
6413 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006414 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006415 child->name, NULL);
6416 child = child->next;
6417 }
6418 while (IS_SCHEMA(child, "annotation")) {
6419 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6420 if (schema->annot == NULL)
6421 schema->annot = annot;
6422 else
6423 xmlSchemaFreeAnnot(annot);
6424 child = child->next;
6425 }
6426 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006427 ctxt->parentItem = NULL;
6428 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006429}
6430
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006431static xmlSchemaImportPtr
6432xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6433 xmlHashTablePtr *imports,
6434 const xmlChar *nsName)
6435{
6436 xmlSchemaImportPtr ret;
6437
6438 if (*imports == NULL) {
6439 *imports = xmlHashCreate(10);
6440 if (*imports == NULL) {
6441 xmlSchemaPCustomErr(ctxt,
6442 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6443 NULL, NULL, (xmlNodePtr) ctxt->doc,
6444 "Internal error: failed to build the import table",
6445 NULL);
6446 return (NULL);
6447 }
6448 }
6449 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6450 if (ret == NULL) {
6451 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6452 return (NULL);
6453 }
6454 memset(ret, 0, sizeof(xmlSchemaImport));
6455 if (nsName == NULL)
6456 nsName = XML_SCHEMAS_NO_NAMESPACE;
6457 xmlHashAddEntry(*imports, nsName, ret);
6458
6459 return (ret);
6460}
6461
6462static int
6463xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006464 xmlSchemaPtr schema,
6465 xmlNodePtr node,
6466 const xmlChar *nsName,
6467 const xmlChar *location,
6468 xmlDocPtr *doc,
6469 const xmlChar **targetNamespace,
6470 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006471{
6472 xmlParserCtxtPtr parserCtxt;
6473 xmlSchemaImportPtr import;
6474 const xmlChar *ns;
6475 xmlNodePtr root;
6476
6477 /*
6478 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6479 * <xsi:noNamespaceSchemaLocation>.
6480 */
6481 *doc = NULL;
6482 /*
6483 * Given that the schemaLocation [attribute] is only a hint, it is open
6484 * to applications to ignore all but the first <import> for a given
6485 * namespace, regardless of the ·actual value· of schemaLocation, but
6486 * such a strategy risks missing useful information when new
6487 * schemaLocations are offered.
6488 *
6489 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6490 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6491 * valid or not.
6492 * We will follow XSV here.
6493 */
6494 if (location == NULL) {
6495 /*
6496 * Schema Document Location Strategy:
6497 *
6498 * 3 Based on the namespace name, identify an existing schema document,
6499 * either as a resource which is an XML document or a <schema> element
6500 * information item, in some local schema repository;
6501 *
6502 * 5 Attempt to resolve the namespace name to locate such a resource.
6503 *
6504 * NOTE: Those stategies are not supported, so we will skip.
6505 */
6506 return (0);
6507 }
6508 if (nsName == NULL)
6509 ns = XML_SCHEMAS_NO_NAMESPACE;
6510 else
6511 ns = nsName;
6512
6513 import = xmlHashLookup(schema->schemasImports, ns);
6514 if (import != NULL) {
6515 /*
6516 * There was a valid resource for the specified namespace already
6517 * defined, so skip.
6518 * TODO: This might be changed someday to allow import of
6519 * components from multiple documents for a single target namespace.
6520 */
6521 return (0);
6522 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006523
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006524 /*
6525 * Schema Document Location Strategy:
6526 *
6527 * 2 Based on the location URI, identify an existing schema document,
6528 * either as a resource which is an XML document or a <schema> element
6529 * information item, in some local schema repository;
6530 *
6531 * 4 Attempt to resolve the location URI, to locate a resource on the
6532 * web which is or contains or references a <schema> element;
6533 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6534 *
6535 */
6536 if ((absolute == 0) && (node != NULL)) {
6537 xmlChar *base, *URI;
6538
6539 base = xmlNodeGetBase(node->doc, node);
6540 if (base == NULL) {
6541 URI = xmlBuildURI(location, node->doc->URL);
6542 } else {
6543 URI = xmlBuildURI(location, base);
6544 xmlFree(base);
6545 }
6546 if (URI != NULL) {
6547 location = xmlDictLookup(ctxt->dict, URI, -1);
6548 xmlFree(URI);
6549 }
6550 }
6551 parserCtxt = xmlNewParserCtxt();
6552 if (parserCtxt == NULL) {
6553 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6554 "allocating a parser context", NULL);
6555 return(-1);
6556 }
6557
6558 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6559 NULL, SCHEMAS_PARSE_OPTIONS);
6560
6561 /*
6562 * 2.1 The referent is (a fragment of) a resource which is an
6563 * XML document (see clause 1.1), which in turn corresponds to
6564 * a <schema> element information item in a well-formed information
6565 * set, which in turn corresponds to a valid schema.
6566 * TODO: What to do with the "fragment" stuff?
6567 *
6568 * 2.2 The referent is a <schema> element information item in
6569 * a well-formed information set, which in turn corresponds
6570 * to a valid schema.
6571 * NOTE: 2.2 won't apply, since only XML documents will be processed
6572 * here.
6573 */
6574 if (*doc == NULL) {
6575 xmlErrorPtr lerr;
6576 /*
6577 * It is *not* an error for the application schema reference
6578 * strategy to fail.
6579 *
6580 * If the doc is NULL and the parser error is an IO error we
6581 * will assume that the resource could not be located or accessed.
6582 *
6583 * TODO: Try to find specific error codes to react only on
6584 * localisation failures.
6585 *
6586 * TODO, FIXME: Check the spec: is a namespace added to the imported
6587 * namespaces, even if the schemaLocation did not provide
6588 * a resource? I guess so, since omitting the "schemaLocation"
6589 * attribute, imports a namespace as well.
6590 */
6591 lerr = xmlGetLastError();
6592 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6593 xmlFreeParserCtxt(parserCtxt);
6594 return(0);
6595 }
6596
6597 xmlSchemaPCustomErr(ctxt,
6598 XML_SCHEMAP_SRC_IMPORT_2_1,
6599 NULL, NULL, node,
6600 "Failed to parse the resource '%s' for import",
6601 location);
6602 xmlFreeParserCtxt(parserCtxt);
6603 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6604 }
6605 xmlFreeParserCtxt(parserCtxt);
6606
6607 root = xmlDocGetRootElement(*doc);
6608 if (root == NULL) {
6609 xmlSchemaPCustomErr(ctxt,
6610 XML_SCHEMAP_SRC_IMPORT_2_1,
6611 NULL, NULL, node,
6612 "The XML document '%s' to be imported has no document "
6613 "element", location);
6614 xmlFreeDoc(*doc);
6615 *doc = NULL;
6616 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6617 }
6618
6619 xmlSchemaCleanupDoc(ctxt, root);
6620
6621 if (!IS_SCHEMA(root, "schema")) {
6622 xmlSchemaPCustomErr(ctxt,
6623 XML_SCHEMAP_SRC_IMPORT_2_1,
6624 NULL, NULL, node,
6625 "The XML document '%s' to be imported is not a XML schema document",
6626 location);
6627 xmlFreeDoc(*doc);
6628 *doc = NULL;
6629 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6630 }
6631 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6632 /*
6633 * Schema Representation Constraint: Import Constraints and Semantics
6634 */
6635 if (nsName == NULL) {
6636 if (*targetNamespace != NULL) {
6637 xmlSchemaPCustomErr(ctxt,
6638 XML_SCHEMAP_SRC_IMPORT_3_2,
6639 NULL, NULL, node,
6640 "The XML schema to be imported is not expected "
6641 "to have a target namespace; this differs from "
6642 "its target namespace of '%s'", *targetNamespace);
6643 xmlFreeDoc(*doc);
6644 *doc = NULL;
6645 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6646 }
6647 } else {
6648 if (*targetNamespace == NULL) {
6649 xmlSchemaPCustomErr(ctxt,
6650 XML_SCHEMAP_SRC_IMPORT_3_1,
6651 NULL, NULL, node,
6652 "The XML schema to be imported is expected to have a target "
6653 "namespace of '%s'", nsName);
6654 xmlFreeDoc(*doc);
6655 *doc = NULL;
6656 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6657 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6658 xmlSchemaPCustomErrExt(ctxt,
6659 XML_SCHEMAP_SRC_IMPORT_3_1,
6660 NULL, NULL, node,
6661 "The XML schema to be imported is expected to have a "
6662 "target namespace of '%s'; this differs from "
6663 "its target namespace of '%s'",
6664 nsName, *targetNamespace, NULL);
6665 xmlFreeDoc(*doc);
6666 *doc = NULL;
6667 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6668 }
6669 }
6670
6671 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6672 if (import == NULL) {
6673 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6674 NULL, NULL, NULL,
6675 "Internal error: xmlSchemaAcquireSchemaDoc, "
6676 "failed to build import table", NULL);
6677 xmlFreeDoc(*doc);
6678 *doc = NULL;
6679 return (-1);
6680 }
6681 import->schemaLocation = location;
6682 import->doc = *doc;
6683 return (0);
6684}
William M. Brack2f2a6632004-08-20 23:09:47 +00006685
6686/**
6687 * xmlSchemaParseImport:
6688 * @ctxt: a schema validation context
6689 * @schema: the schema being built
6690 * @node: a subtree containing XML Schema informations
6691 *
6692 * parse a XML schema Import definition
6693 * *WARNING* this interface is highly subject to change
6694 *
6695 * Returns 0 in case of success, a positive error code if
6696 * not valid and -1 in case of an internal error.
6697 */
6698static int
6699xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6700 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006701{
6702 xmlNodePtr child;
6703 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006704 const xmlChar *schemaLocation = NULL;
6705 const xmlChar *targetNamespace, *oldTNS, *url;
6706 xmlAttrPtr attr;
6707 xmlDocPtr doc;
6708 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006710
6711
6712 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6713 return (-1);
6714
6715 /*
6716 * Check for illegal attributes.
6717 */
6718 attr = node->properties;
6719 while (attr != NULL) {
6720 if (attr->ns == NULL) {
6721 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6722 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6723 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6724 xmlSchemaPIllegalAttrErr(ctxt,
6725 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6726 NULL, NULL, attr);
6727 }
6728 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6729 xmlSchemaPIllegalAttrErr(ctxt,
6730 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6731 NULL, NULL, attr);
6732 }
6733 attr = attr->next;
6734 }
6735 /*
6736 * Extract and validate attributes.
6737 */
6738 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6739 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6740 &namespace) != 0) {
6741 xmlSchemaPSimpleTypeErr(ctxt,
6742 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6743 NULL, NULL, node,
6744 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6745 NULL, namespace, NULL, NULL, NULL);
6746 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6747 }
6748
6749 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6750 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6751 &schemaLocation) != 0) {
6752 xmlSchemaPSimpleTypeErr(ctxt,
6753 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6754 NULL, NULL, node,
6755 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6756 NULL, namespace, NULL, NULL, NULL);
6757 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6758 }
6759 /*
6760 * And now for the children...
6761 */
6762 child = node->children;
6763 if (IS_SCHEMA(child, "annotation")) {
6764 /*
6765 * the annotation here is simply discarded ...
6766 */
6767 child = child->next;
6768 }
6769 if (child != NULL) {
6770 xmlSchemaPContentErr(ctxt,
6771 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6772 NULL, NULL, node, child, NULL,
6773 "(annotation?)");
6774 }
6775 /*
6776 * Apply additional constraints.
6777 */
6778 if (namespace != NULL) {
6779 /*
6780 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6781 * must not match the ·actual value· of the enclosing <schema>'s
6782 * targetNamespace [attribute].
6783 */
6784 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6785 xmlSchemaPCustomErr(ctxt,
6786 XML_SCHEMAP_SRC_IMPORT_1_1,
6787 NULL, NULL, node,
6788 "The value of the attribute 'namespace' must not match "
6789 "the target namespace '%s' of the importing schema",
6790 schema->targetNamespace);
6791 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6792 }
6793 } else {
6794 /*
6795 * 1.2 If the namespace [attribute] is not present, then the enclosing
6796 * <schema> must have a targetNamespace [attribute].
6797 */
6798 if (schema->targetNamespace == NULL) {
6799 xmlSchemaPCustomErr(ctxt,
6800 XML_SCHEMAP_SRC_IMPORT_1_2,
6801 NULL, NULL, node,
6802 "The attribute 'namespace' must be existent if "
6803 "the importing schema has no target namespace",
6804 NULL);
6805 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6806 }
6807 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006808 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006809 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006810 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006811 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6812 schemaLocation, &doc, &targetNamespace, 0);
6813 if (ret != 0) {
6814 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006815 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006816 return (ret);
6817 } else if (doc != NULL) {
6818 /*
6819 * Save and reset the context & schema.
6820 */
6821 url = ctxt->URL;
6822 /* TODO: Is using the doc->URL here correct? */
6823 ctxt->URL = doc->URL;
6824 flags = schema->flags;
6825 oldTNS = schema->targetNamespace;
6826 /*
6827 * Parse the schema.
6828 */
6829 root = xmlDocGetRootElement(doc);
6830 xmlSchemaClearSchemaDefaults(schema);
6831 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6832 schema->targetNamespace = targetNamespace;
6833 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6834 /*
6835 * Restore the context & schema.
6836 */
6837 schema->flags = flags;
6838 schema->targetNamespace = oldTNS;
6839 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00006840 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006841
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006842 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00006843}
6844
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006845/**
6846 * xmlSchemaParseInclude:
6847 * @ctxt: a schema validation context
6848 * @schema: the schema being built
6849 * @node: a subtree containing XML Schema informations
6850 *
6851 * parse a XML schema Include definition
6852 *
William M. Bracke7091952004-05-11 15:09:58 +00006853 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006854 * 1 in case of success.
6855 */
6856static int
6857xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6858 xmlNodePtr node)
6859{
6860 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006861 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006862 xmlDocPtr doc;
6863 xmlNodePtr root;
6864 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006865 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006866 xmlAttrPtr attr;
6867 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006868
6869
6870 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6871 return (-1);
6872
6873 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006874 * Check for illegal attributes.
6875 */
6876 attr = node->properties;
6877 while (attr != NULL) {
6878 if (attr->ns == NULL) {
6879 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6880 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6881 xmlSchemaPIllegalAttrErr(ctxt,
6882 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6883 NULL, NULL, attr);
6884 }
6885 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6886 xmlSchemaPIllegalAttrErr(ctxt,
6887 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6888 NULL, NULL, attr);
6889 }
6890 attr = attr->next;
6891 }
6892 /*
6893 * Extract and validate attributes.
6894 */
6895 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006896 * Preliminary step, extract the URI-Reference for the include and
6897 * make an URI from the base.
6898 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006899 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6900 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006901 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006902 xmlChar *uri = NULL;
6903
6904 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6905 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6906 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006907 base = xmlNodeGetBase(node->doc, node);
6908 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006909 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006910 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006911 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006912 xmlFree(base);
6913 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006914 if (uri != NULL) {
6915 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6916 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006917 }
6918 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006919 xmlSchemaPMissingAttrErr(ctxt,
6920 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6921 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006922 return (-1);
6923 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006924 /*
6925 * And now for the children...
6926 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006927 child = node->children;
6928 while (IS_SCHEMA(child, "annotation")) {
6929 /*
6930 * the annotations here are simply discarded ...
6931 */
6932 child = child->next;
6933 }
6934 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006935 xmlSchemaPContentErr(ctxt,
6936 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6937 NULL, NULL, node, child, NULL,
6938 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006939 }
6940
6941 /*
6942 * First step is to parse the input document into an DOM/Infoset
6943 */
6944 doc = xmlReadFile((const char *) schemaLocation, NULL,
6945 SCHEMAS_PARSE_OPTIONS);
6946 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006947 /*
6948 * TODO: It is not an error for the ·actual value· of the
6949 * schemaLocation [attribute] to fail to resolve it all, in which
6950 * case no corresponding inclusion is performed.
6951 * So do we need a warning report here?
6952 */
6953 xmlSchemaPCustomErr(ctxt,
6954 XML_SCHEMAP_FAILED_LOAD,
6955 NULL, NULL, node,
6956 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006957 return(-1);
6958 }
6959
6960 /*
6961 * Then extract the root of the schema
6962 */
6963 root = xmlDocGetRootElement(doc);
6964 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006965 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006966 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006967 NULL, NULL, node,
6968 "The included document '%s' has no document "
6969 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006970 xmlFreeDoc(doc);
6971 return (-1);
6972 }
6973
6974 /*
6975 * Remove all the blank text nodes
6976 */
6977 xmlSchemaCleanupDoc(ctxt, root);
6978
6979 /*
6980 * Check the schemas top level element
6981 */
6982 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006983 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006984 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00006985 NULL, NULL, node,
6986 "The document '%s' to be included is not a schema document",
6987 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006988 xmlFreeDoc(doc);
6989 return (-1);
6990 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006991
William M. Brack2f2a6632004-08-20 23:09:47 +00006992 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006993 /*
6994 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6995 * value· is identical to the ·actual value· of the targetNamespace
6996 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6997 */
6998 if (targetNamespace != NULL) {
6999 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007000 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007001 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007002 NULL, NULL, node,
7003 "The target namespace of the included schema "
7004 "'%s' has to be absent, since the including schema "
7005 "has no target namespace",
7006 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007007 xmlFreeDoc(doc);
7008 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007009 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7010 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007011 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007012 NULL, NULL, node,
7013 "The target namespace '%s' of the included schema '%s' "
7014 "differs from '%s' of the including schema",
7015 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007016 xmlFreeDoc(doc);
7017 return (-1);
7018 }
7019 } else if (schema->targetNamespace != NULL) {
7020 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7021 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7022 } else
7023 wasConvertingNs = 1;
7024 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007025 /*
7026 * register the include
7027 */
7028 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7029 if (include == NULL) {
7030 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7031 xmlFreeDoc(doc);
7032 return (-1);
7033 }
7034
7035 memset(include, 0, sizeof(xmlSchemaInclude));
7036 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7037 include->doc = doc;
7038 include->next = schema->includes;
7039 schema->includes = include;
7040
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007041 /*
7042 * parse the declarations in the included file like if they
7043 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007044 */
7045 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007046 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007047 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007048 /*
7049 * The default values ("blockDefault", "elementFormDefault", etc.)
7050 * are set to the values of the included schema and restored afterwards.
7051 */
7052 saveFlags = schema->flags;
7053 xmlSchemaClearSchemaDefaults(schema);
7054 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007055 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007056 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007057 /*
7058 * Remove the converting flag.
7059 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007060 if ((wasConvertingNs == 0) &&
7061 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007062 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007063 return (1);
7064}
7065
7066/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007067 * xmlSchemaParseChoice:
7068 * @ctxt: a schema validation context
7069 * @schema: the schema being built
7070 * @node: a subtree containing XML Schema informations
7071 *
7072 * parse a XML schema Choice definition
7073 * *WARNING* this interface is highly subject to change
7074 *
William M. Bracke7091952004-05-11 15:09:58 +00007075 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007076 * 1 in case of success.
7077 */
7078static xmlSchemaTypePtr
7079xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007080 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007081{
7082 xmlSchemaTypePtr type, subtype, last = NULL;
7083 xmlNodePtr child = NULL;
7084 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007085 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007086
7087 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7088 return (NULL);
7089
7090
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007091 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007092 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007093 if (type == NULL)
7094 return (NULL);
7095 type->node = node;
7096 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007097 /*
7098 * Check for illegal attributes.
7099 */
7100 attr = node->properties;
7101 while (attr != NULL) {
7102 if (attr->ns == NULL) {
7103 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7104 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7105 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7106 xmlSchemaPIllegalAttrErr(ctxt,
7107 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7108 NULL, type, attr);
7109 }
7110 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7111 xmlSchemaPIllegalAttrErr(ctxt,
7112 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7113 NULL, type, attr);
7114 }
7115 attr = attr->next;
7116 }
7117 /*
7118 * Extract and validate attributes.
7119 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007120 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007121 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7122 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7123 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007124 /*
7125 * And now for the children...
7126 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007127 child = node->children;
7128 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007129 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7130 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007131 }
7132 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007133 (IS_SCHEMA(child, "group")) ||
7134 (IS_SCHEMA(child, "any")) ||
7135 (IS_SCHEMA(child, "choice")) ||
7136 (IS_SCHEMA(child, "sequence"))) {
7137 subtype = NULL;
7138 if (IS_SCHEMA(child, "element")) {
7139 subtype = (xmlSchemaTypePtr)
7140 xmlSchemaParseElement(ctxt, schema, child, 0);
7141 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007142 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007143 } else if (IS_SCHEMA(child, "any")) {
7144 subtype = xmlSchemaParseAny(ctxt, schema, child);
7145 } else if (IS_SCHEMA(child, "sequence")) {
7146 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7147 } else if (IS_SCHEMA(child, "choice")) {
7148 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7149 }
7150 if (subtype != NULL) {
7151 if (last == NULL) {
7152 type->subtypes = subtype;
7153 last = subtype;
7154 } else {
7155 last->next = subtype;
7156 last = subtype;
7157 }
7158 last->next = NULL;
7159 }
7160 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007161 }
7162 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007163 /* TODO: error code. */
7164 xmlSchemaPContentErr(ctxt,
7165 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7166 NULL, type, node, child, NULL,
7167 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007168 }
7169
7170 return (type);
7171}
7172
7173/**
7174 * xmlSchemaParseSequence:
7175 * @ctxt: a schema validation context
7176 * @schema: the schema being built
7177 * @node: a subtree containing XML Schema informations
7178 *
7179 * parse a XML schema Sequence definition
7180 * *WARNING* this interface is highly subject to change
7181 *
William M. Bracke7091952004-05-11 15:09:58 +00007182 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007183 * 1 in case of success.
7184 */
7185static xmlSchemaTypePtr
7186xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007187 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007188{
7189 xmlSchemaTypePtr type, subtype, last = NULL;
7190 xmlNodePtr child = NULL;
7191 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007192 xmlAttrPtr attr;
7193 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007194
7195 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7196 return (NULL);
7197
William M. Brack2f2a6632004-08-20 23:09:47 +00007198 oldcontainer = ctxt->container;
7199 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7200 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007201 if (type == NULL)
7202 return (NULL);
7203 type->node = node;
7204 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007205 /*
7206 * Check for illegal attributes.
7207 */
7208 attr = node->properties;
7209 while (attr != NULL) {
7210 if (attr->ns == NULL) {
7211 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7212 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7213 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7214 xmlSchemaPIllegalAttrErr(ctxt,
7215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7216 NULL, type, attr);
7217 }
7218 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7219 xmlSchemaPIllegalAttrErr(ctxt,
7220 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7221 NULL, type, attr);
7222 }
7223 attr = attr->next;
7224 }
7225 /*
7226 * Extract and validate attributes.
7227 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007228 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007229 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7230 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7231 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007232 /*
7233 * And now for the children...
7234 */
7235 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007236 child = node->children;
7237 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007238 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7239 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007240 }
7241 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007242 (IS_SCHEMA(child, "group")) ||
7243 (IS_SCHEMA(child, "any")) ||
7244 (IS_SCHEMA(child, "choice")) ||
7245 (IS_SCHEMA(child, "sequence"))) {
7246 subtype = NULL;
7247 if (IS_SCHEMA(child, "element")) {
7248 subtype = (xmlSchemaTypePtr)
7249 xmlSchemaParseElement(ctxt, schema, child, 0);
7250 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007251 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007252 } else if (IS_SCHEMA(child, "any")) {
7253 subtype = xmlSchemaParseAny(ctxt, schema, child);
7254 } else if (IS_SCHEMA(child, "choice")) {
7255 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7256 } else if (IS_SCHEMA(child, "sequence")) {
7257 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7258 }
7259 if (subtype != NULL) {
7260 if (last == NULL) {
7261 type->subtypes = subtype;
7262 last = subtype;
7263 } else {
7264 last->next = subtype;
7265 last = subtype;
7266 }
7267 last->next = NULL;
7268 }
7269 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007270 }
7271 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007272 xmlSchemaPContentErr(ctxt,
7273 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7274 NULL, type, node, child, NULL,
7275 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007276 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007277 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007278
7279 return (type);
7280}
7281
7282/**
7283 * xmlSchemaParseRestriction:
7284 * @ctxt: a schema validation context
7285 * @schema: the schema being built
7286 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007287 *
7288 * parse a XML schema Restriction definition
7289 * *WARNING* this interface is highly subject to change
7290 *
7291 * Returns the type definition or NULL in case of error
7292 */
7293static xmlSchemaTypePtr
7294xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007295 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007296{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007297 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007298 xmlNodePtr child = NULL;
7299 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007300 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007301 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007302
7303 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7304 return (NULL);
7305
7306 oldcontainer = ctxt->container;
7307
William M. Brack2f2a6632004-08-20 23:09:47 +00007308 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7309 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007310 if (type == NULL)
7311 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007312 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007313 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007314 /*
7315 * Check for illegal attributes.
7316 */
7317 attr = node->properties;
7318 while (attr != NULL) {
7319 if (attr->ns == NULL) {
7320 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7321 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7322 xmlSchemaPIllegalAttrErr(ctxt,
7323 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7324 NULL, type, attr);
7325 }
7326 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7327 xmlSchemaPIllegalAttrErr(ctxt,
7328 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7329 NULL, type, attr);
7330 }
7331 attr = attr->next;
7332 }
7333 /*
7334 * Extract and validate attributes.
7335 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007336 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007337 /*
7338 * Attribute "base".
7339 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007340 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007341 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007342 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7343 /* TODO: Think about the error code. */
7344 xmlSchemaPMissingAttrErr(ctxt,
7345 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7346 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007347 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007348 /*
7349 * And now for the children...
7350 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007351 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007352 child = node->children;
7353 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007354 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7355 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007356 }
7357 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007358 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7359 if (IS_SCHEMA(child, "all")) {
7360 subtype = (xmlSchemaTypePtr)
7361 xmlSchemaParseAll(ctxt, schema, child);
7362 child = child->next;
7363 type->subtypes = subtype;
7364 } else if (IS_SCHEMA(child, "choice")) {
7365 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7366 child = child->next;
7367 type->subtypes = subtype;
7368 } else if (IS_SCHEMA(child, "sequence")) {
7369 subtype = (xmlSchemaTypePtr)
7370 xmlSchemaParseSequence(ctxt, schema, child);
7371 child = child->next;
7372 type->subtypes = subtype;
7373 } else if (IS_SCHEMA(child, "group")) {
7374 subtype = (xmlSchemaTypePtr)
7375 xmlSchemaParseGroup(ctxt, schema, child, 0);
7376 child = child->next;
7377 type->subtypes = subtype;
7378 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007379 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7380 if (IS_SCHEMA(child, "simpleType")) {
7381 if (type->base != NULL) {
7382 /*
7383 * src-restriction-base-or-simpleType
7384 * Either the base [attribute] or the simpleType [child] of the
7385 * <restriction> element must be present, but not both.
7386 */
7387 xmlSchemaPContentErr(ctxt,
7388 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7389 NULL, NULL, type->node, child,
7390 "The attribute 'base' and the <simpleType> child are "
7391 "mutually exclusive", NULL);
7392 } else {
7393 subtype = (xmlSchemaTypePtr)
7394 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7395 type->baseType = subtype;
7396 }
7397 child = child->next;
7398 }
7399 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007400 if (IS_SCHEMA(child, "simpleType")) {
7401 subtype = (xmlSchemaTypePtr)
7402 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007403 type->subtypes = subtype;
7404 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007405 }
7406 }
7407 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7408 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7409 xmlSchemaFacetPtr facet, lastfacet = NULL;
7410
Daniel Veillard01fa6152004-06-29 17:04:39 +00007411 /*
7412 * Add the facets to the parent simpleType/complexType.
7413 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007414 /*
7415 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7416 * Simple Type Definition Schema Representation Constraint:
7417 * *Single Facet Value*
7418 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007419 while ((IS_SCHEMA(child, "minInclusive")) ||
7420 (IS_SCHEMA(child, "minExclusive")) ||
7421 (IS_SCHEMA(child, "maxInclusive")) ||
7422 (IS_SCHEMA(child, "maxExclusive")) ||
7423 (IS_SCHEMA(child, "totalDigits")) ||
7424 (IS_SCHEMA(child, "fractionDigits")) ||
7425 (IS_SCHEMA(child, "pattern")) ||
7426 (IS_SCHEMA(child, "enumeration")) ||
7427 (IS_SCHEMA(child, "whiteSpace")) ||
7428 (IS_SCHEMA(child, "length")) ||
7429 (IS_SCHEMA(child, "maxLength")) ||
7430 (IS_SCHEMA(child, "minLength"))) {
7431 facet = xmlSchemaParseFacet(ctxt, schema, child);
7432 if (facet != NULL) {
7433 if (lastfacet == NULL)
7434 ctxt->ctxtType->facets = facet;
7435 else
7436 lastfacet->next = facet;
7437 lastfacet = facet;
7438 lastfacet->next = NULL;
7439 }
7440 child = child->next;
7441 }
7442 /*
7443 * Create links for derivation and validation.
7444 */
7445 if (lastfacet != NULL) {
7446 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7447
7448 facet = ctxt->ctxtType->facets;
7449 do {
7450 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7451 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007452 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007453 xmlFree(facetLink);
7454 return (NULL);
7455 }
7456 facetLink->facet = facet;
7457 facetLink->next = NULL;
7458 if (lastFacetLink == NULL)
7459 ctxt->ctxtType->facetSet = facetLink;
7460 else
7461 lastFacetLink->next = facetLink;
7462 lastFacetLink = facetLink;
7463 facet = facet->next;
7464 } while (facet != NULL);
7465 }
7466 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007467 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7468 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7469 if (IS_SCHEMA(child, "anyAttribute")) {
7470 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7471 child = child->next;
7472 }
7473 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007474 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007475 /* TODO: Think about the error code. */
7476 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7477 xmlSchemaPContentErr(ctxt,
7478 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7479 NULL, type, node, child, NULL,
7480 "annotation?, (group | all | choice | sequence)?, "
7481 "((attribute | attributeGroup)*, anyAttribute?))");
7482 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7483 xmlSchemaPContentErr(ctxt,
7484 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7485 NULL, type, node, child, NULL,
7486 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7487 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7488 "length | minLength | maxLength | enumeration | whiteSpace | "
7489 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7490 } else {
7491 /* Simple type */
7492 xmlSchemaPContentErr(ctxt,
7493 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7494 NULL, type, node, child, NULL,
7495 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7496 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7497 "length | minLength | maxLength | enumeration | whiteSpace | "
7498 "pattern)*))");
7499 }
7500 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007501 ctxt->container = oldcontainer;
7502 return (type);
7503}
7504
7505/**
7506 * xmlSchemaParseExtension:
7507 * @ctxt: a schema validation context
7508 * @schema: the schema being built
7509 * @node: a subtree containing XML Schema informations
7510 *
7511 * parse a XML schema Extension definition
7512 * *WARNING* this interface is highly subject to change
7513 *
7514 * Returns the type definition or NULL in case of error
7515 */
7516static xmlSchemaTypePtr
7517xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007518 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007519{
7520 xmlSchemaTypePtr type, subtype;
7521 xmlNodePtr child = NULL;
7522 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007523 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007524
7525 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7526 return (NULL);
7527
7528 oldcontainer = ctxt->container;
7529
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007530 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007531 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007532 if (type == NULL)
7533 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007534 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007535 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007536 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007537 ctxt->container = name;
7538
7539 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7540 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007541 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007542 "<extension>: The attribute \"base\" is missing.\n",
7543 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007544 }
7545 child = node->children;
7546 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007547 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7548 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007549 }
7550 subtype = NULL;
7551
7552 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007553 subtype = xmlSchemaParseAll(ctxt, schema, child);
7554 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007555 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007556 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007558 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007559 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7560 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007561 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007562 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007563 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007564 }
7565 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007566 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007567 if ((ctxt->ctxtType != NULL) &&
7568 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7569 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7570 if (IS_SCHEMA(child, "anyAttribute")) {
7571 ctxt->ctxtType->attributeWildcard =
7572 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7573 child = child->next;
7574 }
7575 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007576 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007577 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007578 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7579 "<extension> has unexpected content.\n", type->name,
7580 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007581 }
7582 ctxt->container = oldcontainer;
7583 return (type);
7584}
7585
7586/**
7587 * xmlSchemaParseSimpleContent:
7588 * @ctxt: a schema validation context
7589 * @schema: the schema being built
7590 * @node: a subtree containing XML Schema informations
7591 *
7592 * parse a XML schema SimpleContent definition
7593 * *WARNING* this interface is highly subject to change
7594 *
7595 * Returns the type definition or NULL in case of error
7596 */
7597static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007598xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7599 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007600{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007601 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007602 xmlNodePtr child = NULL;
7603 xmlChar name[30];
7604
7605 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7606 return (NULL);
7607
William M. Bracke7091952004-05-11 15:09:58 +00007608 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007609 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007610 if (type == NULL)
7611 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007612 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007613 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007614 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007615
7616 child = node->children;
7617 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007618 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7619 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007620 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007621 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007622 ctxt->parentItem = type;
7623 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007624 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007625 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007626 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007627 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007628 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007629 subtype = (xmlSchemaTypePtr)
7630 xmlSchemaParseExtension(ctxt, schema, child);
7631 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007632 }
7633 type->subtypes = subtype;
7634 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007635 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007636 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7637 "<simpleContent> has unexpected content.\n",
7638 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007639 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007640 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007641 return (type);
7642}
7643
7644/**
7645 * xmlSchemaParseComplexContent:
7646 * @ctxt: a schema validation context
7647 * @schema: the schema being built
7648 * @node: a subtree containing XML Schema informations
7649 *
7650 * parse a XML schema ComplexContent definition
7651 * *WARNING* this interface is highly subject to change
7652 *
7653 * Returns the type definition or NULL in case of error
7654 */
7655static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007656xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7657 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007658{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007659 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007660 xmlNodePtr child = NULL;
7661 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007662 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007663
7664 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7665 return (NULL);
7666
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007667 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007668 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007669 if (type == NULL)
7670 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007671 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007672 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007673 /*
7674 * Check for illegal attributes.
7675 */
7676 attr = node->properties;
7677 while (attr != NULL) {
7678 if (attr->ns == NULL) {
7679 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7680 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7681 {
7682 xmlSchemaPIllegalAttrErr(ctxt,
7683 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7684 NULL, NULL, attr);
7685 }
7686 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7687 xmlSchemaPIllegalAttrErr(ctxt,
7688 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7689 NULL, NULL, attr);
7690 }
7691 attr = attr->next;
7692 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007693 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007694 /*
7695 * Handle attribute 'mixed'.
7696 */
7697 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7698 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7699 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7700 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007701 child = node->children;
7702 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007703 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7704 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007705 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007706 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007707 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007708 subtype = NULL;
7709 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007710 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007711 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007712 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007713 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007714 subtype = (xmlSchemaTypePtr)
7715 xmlSchemaParseExtension(ctxt, schema, child);
7716 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007717 }
7718 type->subtypes = subtype;
7719 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007720 xmlSchemaPContentErr(ctxt,
7721 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7722 NULL, NULL, node, child,
7723 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007724 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007725 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007726 return (type);
7727}
7728
7729/**
7730 * xmlSchemaParseComplexType:
7731 * @ctxt: a schema validation context
7732 * @schema: the schema being built
7733 * @node: a subtree containing XML Schema informations
7734 *
7735 * parse a XML schema Complex Type definition
7736 * *WARNING* this interface is highly subject to change
7737 *
7738 * Returns the type definition or NULL in case of error
7739 */
7740static xmlSchemaTypePtr
7741xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007742 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007743{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007744 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007745 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007746 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007747 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007748 xmlAttrPtr attr;
7749 const xmlChar *attrValue;
7750 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00007751
7752 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7753 return (NULL);
7754
Daniel Veillard01fa6152004-06-29 17:04:39 +00007755 ctxtType = ctxt->ctxtType;
7756
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007757 if (topLevel) {
7758 attr = xmlSchemaGetPropNode(node, "name");
7759 if (attr == NULL) {
7760 xmlSchemaPMissingAttrErr(ctxt,
7761 XML_SCHEMAP_S4S_ATTR_MISSING,
7762 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7763 "name", NULL);
7764 return (NULL);
7765 } else if (xmlSchemaPValAttrNode(ctxt,
7766 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7767 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7768 return (NULL);
7769 }
7770 }
7771
7772 if (topLevel == 0) {
7773 char buf[40];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007774
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007775 /*
7776 * Parse as local complex type definition.
7777 */
7778 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7779 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7780 if (type == NULL)
7781 return (NULL);
7782 name = (const xmlChar *) buf;
7783 type->node = node;
7784 type->type = XML_SCHEMA_TYPE_COMPLEX;
7785 /*
7786 * TODO: We need the target namespace.
7787 */
7788 } else {
7789 /*
7790 * Parse as global complex type definition.
7791 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007792 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007793 if (type == NULL)
7794 return (NULL);
7795 type->node = node;
7796 type->type = XML_SCHEMA_TYPE_COMPLEX;
7797 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7798 /*
7799 * Set defaults.
7800 */
7801 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7802 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
7803 }
7804 /*
7805 * Handle attributes.
7806 */
7807 attr = node->properties;
7808 while (attr != NULL) {
7809 if (attr->ns == NULL) {
7810 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7811 /*
7812 * Attribute "id".
7813 */
7814 type->id = xmlSchemaGetProp(ctxt, node, "id");
7815 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
7816 /*
7817 * Attribute "mixed".
7818 */
7819 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7820 (xmlNodePtr) attr))
7821 type->flags |= XML_SCHEMAS_TYPE_MIXED;
7822 } else if (topLevel) {
7823 /*
7824 * Attributes of global complex type definitions.
7825 */
7826 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7827 /* Pass. */
7828 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
7829 /*
7830 * Attribute "abstract".
7831 */
7832 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7833 (xmlNodePtr) attr))
7834 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
7835 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
7836 /*
7837 * Attribute "final".
7838 */
7839 attrValue = xmlSchemaGetNodeContent(ctxt,
7840 (xmlNodePtr) attr);
7841 if (xmlSchemaPValAttrBlockFinal(attrValue,
7842 &(type->flags),
7843 -1,
7844 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
7845 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
7846 -1, -1, -1) != 0)
7847 {
7848 xmlSchemaPSimpleTypeErr(ctxt,
7849 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7850 &des, type, (xmlNodePtr) attr,
7851 NULL,
7852 "(#all | List of (extension | restriction))",
7853 attrValue, NULL, NULL, NULL);
7854 }
7855 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
7856 /*
7857 * Attribute "block".
7858 */
7859 attrValue = xmlSchemaGetNodeContent(ctxt,
7860 (xmlNodePtr) attr);
7861 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7862 -1,
7863 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
7864 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
7865 -1, -1, -1) != 0) {
7866 xmlSchemaPSimpleTypeErr(ctxt,
7867 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7868 &des, type, (xmlNodePtr) attr,
7869 NULL,
7870 "(#all | List of (extension | restriction)) ",
7871 attrValue, NULL, NULL, NULL);
7872 }
7873 } else {
7874 xmlSchemaPIllegalAttrErr(ctxt,
7875 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7876 &des, type, attr);
7877 }
7878 } else {
7879 xmlSchemaPIllegalAttrErr(ctxt,
7880 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7881 &des, type, attr);
7882 }
7883 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7884 xmlSchemaPIllegalAttrErr(ctxt,
7885 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7886 &des, type, attr);
7887 }
7888 attr = attr->next;
7889 }
7890 /*
7891 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007892 * This will be only changed if a complex type
7893 * inherits an attribute wildcard from a base type.
7894 */
7895 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007896 /*
7897 * And now for the children...
7898 */
7899 oldcontainer = ctxt->container;
7900 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007901 child = node->children;
7902 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007903 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7904 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007905 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007906 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007907 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007908 /*
7909 * 3.4.3 : 2.2
7910 * Specifying mixed='true' when the <simpleContent>
7911 * alternative is chosen has no effect
7912 */
William M. Bracke7091952004-05-11 15:09:58 +00007913 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7914 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007915 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7916 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007917 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007918 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7919 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007920 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007921 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007922 /*
7923 * Parse model groups.
7924 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007925 if (IS_SCHEMA(child, "all")) {
7926 subtype = xmlSchemaParseAll(ctxt, schema, child);
7927 child = child->next;
7928 } else if (IS_SCHEMA(child, "choice")) {
7929 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7930 child = child->next;
7931 } else if (IS_SCHEMA(child, "sequence")) {
7932 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7933 child = child->next;
7934 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007935 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007936 child = child->next;
7937 }
7938 if (subtype != NULL)
7939 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007940 /*
7941 * Parse attribute decls/refs.
7942 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007943 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007944 /*
7945 * Parse attribute wildcard.
7946 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007947 if (IS_SCHEMA(child, "anyAttribute")) {
7948 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7949 child = child->next;
7950 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007951 }
7952 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007953 xmlSchemaPContentErr(ctxt,
7954 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7955 &des, type, node, child,
7956 NULL, "(annotation?, (simpleContent | complexContent | "
7957 "((group | all | choice | sequence)?, ((attribute | "
7958 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007959 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007960 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00007961 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007962 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007963 return (type);
7964}
7965
Daniel Veillard4255d502002-04-16 15:50:10 +00007966/**
7967 * xmlSchemaParseSchema:
7968 * @ctxt: a schema validation context
7969 * @node: a subtree containing XML Schema informations
7970 *
7971 * parse a XML schema definition from a node set
7972 * *WARNING* this interface is highly subject to change
7973 *
7974 * Returns the internal XML Schema structure built from the resource or
7975 * NULL in case of error
7976 */
7977static xmlSchemaPtr
7978xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
7979{
7980 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007981 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007982 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007983 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007984
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007985 /*
7986 * This one is called by xmlSchemaParse only and is used if
7987 * the schema to be parsed was specified via the API; i.e. not
7988 * automatically by the validated instance document.
7989 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007990 if ((ctxt == NULL) || (node == NULL))
7991 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007992
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007993 nberrors = ctxt->nberrors;
7994 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007995 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007996 xmlSchemaImportPtr import;
7997
Daniel Veillard4255d502002-04-16 15:50:10 +00007998 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007999 if (schema == NULL)
8000 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008001 /*
8002 * Disable build of list of items.
8003 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008004 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8005 if (attr != NULL) {
8006 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8007 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8008 /*
8009 * TODO: Should we proceed with an invalid target namespace?
8010 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008011 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8012 } else {
8013 schema->targetNamespace = NULL;
8014 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008015 /*
8016 * Add the current ns name and location to the import table;
8017 * this is needed to have a consistent mechanism, regardless
8018 * if all schemata are constructed dynamically fired by the
8019 * instance or if the schema to be used was specified via
8020 * the API.
8021 */
8022 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8023 schema->targetNamespace);
8024 if (import == NULL) {
8025 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8026 NULL, NULL, (xmlNodePtr) ctxt->doc,
8027 "Internal error: xmlSchemaParseSchema, "
8028 "failed to add an import entry", NULL);
8029 xmlSchemaFree(schema);
8030 schema = NULL;
8031 return (NULL);
8032 }
8033 import->schemaLocation = ctxt->URL;
8034 /*
8035 * NOTE: We won't set the doc here, otherwise it will be freed
8036 * if the import struct is freed.
8037 * import->doc = ctxt->doc;
8038 */
8039
Daniel Veillardc0826a72004-08-10 14:17:33 +00008040 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008041 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008042 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8043 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8044
William M. Brack2f2a6632004-08-20 23:09:47 +00008045 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008046 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8047 } else {
8048 xmlDocPtr doc;
8049
8050 doc = node->doc;
8051
8052 if ((doc != NULL) && (doc->URL != NULL)) {
8053 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8054 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008055 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008056 } else {
8057 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8058 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008059 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008060 }
8061 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008062 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008063 if (ctxt->nberrors != 0) {
8064 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008065 xmlSchemaFree(schema);
8066 schema = NULL;
8067 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008068 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008069 if (schema != NULL)
8070 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008071 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008072#ifdef DEBUG
8073 if (schema == NULL)
8074 xmlGenericError(xmlGenericErrorContext,
8075 "xmlSchemaParse() failed\n");
8076#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008077 return (schema);
8078}
8079
8080/************************************************************************
8081 * *
8082 * Validating using Schemas *
8083 * *
8084 ************************************************************************/
8085
8086/************************************************************************
8087 * *
8088 * Reading/Writing Schemas *
8089 * *
8090 ************************************************************************/
8091
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008092#if 0 /* Will be enabled if it is clear what options are needed. */
8093/**
8094 * xmlSchemaParserCtxtSetOptions:
8095 * @ctxt: a schema parser context
8096 * @options: a combination of xmlSchemaParserOption
8097 *
8098 * Sets the options to be used during the parse.
8099 *
8100 * Returns 0 in case of success, -1 in case of an
8101 * API error.
8102 */
8103static int
8104xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8105 int options)
8106
8107{
8108 int i;
8109
8110 if (ctxt == NULL)
8111 return (-1);
8112 /*
8113 * WARNING: Change the start value if adding to the
8114 * xmlSchemaParseOption.
8115 */
8116 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8117 if (options & 1<<i) {
8118 return (-1);
8119 }
8120 }
8121 ctxt->options = options;
8122 return (0);
8123}
8124
8125/**
8126 * xmlSchemaValidCtxtGetOptions:
8127 * @ctxt: a schema parser context
8128 *
8129 * Returns the option combination of the parser context.
8130 */
8131static int
8132xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8133
8134{
8135 if (ctxt == NULL)
8136 return (-1);
8137 else
8138 return (ctxt->options);
8139}
8140
8141 void *curItems; /* used for dynamic addition of schemata */
8142 int nbCurItems; /* used for dynamic addition of schemata */
8143 int sizeCurItems; /* used for dynamic addition of schemata */
8144
8145#endif
8146
Daniel Veillard4255d502002-04-16 15:50:10 +00008147/**
8148 * xmlSchemaNewParserCtxt:
8149 * @URL: the location of the schema
8150 *
8151 * Create an XML Schemas parse context for that file/resource expected
8152 * to contain an XML Schemas file.
8153 *
8154 * Returns the parser context or NULL in case of error
8155 */
8156xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008157xmlSchemaNewParserCtxt(const char *URL)
8158{
Daniel Veillard4255d502002-04-16 15:50:10 +00008159 xmlSchemaParserCtxtPtr ret;
8160
8161 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008162 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008163
8164 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8165 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008166 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008167 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008168 return (NULL);
8169 }
8170 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008171 ret->dict = xmlDictCreate();
8172 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008173 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008174 return (ret);
8175}
8176
8177/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008178 * xmlSchemaNewParserCtxtUseDict:
8179 * @URL: the location of the schema
8180 * @dict: the dictionary to be used
8181 *
8182 * Create an XML Schemas parse context for that file/resource expected
8183 * to contain an XML Schemas file.
8184 *
8185 * Returns the parser context or NULL in case of error
8186 */
8187static xmlSchemaParserCtxtPtr
8188xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8189{
8190 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008191 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008192 if (URL == NULL)
8193 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008194 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008195
8196 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8197 if (ret == NULL) {
8198 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8199 NULL);
8200 return (NULL);
8201 }
8202 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8203 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008204 xmlDictReference(dict);
8205 if (URL != NULL)
8206 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008207 ret->includes = 0;
8208 return (ret);
8209}
8210
8211
8212/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008213 * xmlSchemaNewMemParserCtxt:
8214 * @buffer: a pointer to a char array containing the schemas
8215 * @size: the size of the array
8216 *
8217 * Create an XML Schemas parse context for that memory buffer expected
8218 * to contain an XML Schemas file.
8219 *
8220 * Returns the parser context or NULL in case of error
8221 */
8222xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008223xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8224{
Daniel Veillard6045c902002-10-09 21:13:59 +00008225 xmlSchemaParserCtxtPtr ret;
8226
8227 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008228 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008229
8230 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8231 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008232 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008233 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008234 return (NULL);
8235 }
8236 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8237 ret->buffer = buffer;
8238 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008239 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008240 return (ret);
8241}
8242
8243/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008244 * xmlSchemaNewDocParserCtxt:
8245 * @doc: a preparsed document tree
8246 *
8247 * Create an XML Schemas parse context for that document.
8248 * NB. The document may be modified during the parsing process.
8249 *
8250 * Returns the parser context or NULL in case of error
8251 */
8252xmlSchemaParserCtxtPtr
8253xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8254{
8255 xmlSchemaParserCtxtPtr ret;
8256
8257 if (doc == NULL)
8258 return (NULL);
8259
8260 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8261 if (ret == NULL) {
8262 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8263 NULL);
8264 return (NULL);
8265 }
8266 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8267 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008268 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008269 /* The application has responsibility for the document */
8270 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008271
8272 return (ret);
8273}
8274
8275/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008276 * xmlSchemaFreeParserCtxt:
8277 * @ctxt: the schema parser context
8278 *
8279 * Free the resources associated to the schema parser context
8280 */
8281void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008282xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8283{
Daniel Veillard4255d502002-04-16 15:50:10 +00008284 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008285 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008286 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008287 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008288 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008289 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008290 xmlFree(ctxt->assemble);
8291 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008292 if (ctxt->vctxt != NULL) {
8293 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8294 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008295 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008296 xmlFree(ctxt);
8297}
8298
8299/************************************************************************
8300 * *
8301 * Building the content models *
8302 * *
8303 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008304
Daniel Veillard4255d502002-04-16 15:50:10 +00008305/**
8306 * xmlSchemaBuildAContentModel:
8307 * @type: the schema type definition
8308 * @ctxt: the schema parser context
8309 * @name: the element name whose content is being built
8310 *
8311 * Generate the automata sequence needed for that type
8312 */
8313static void
8314xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008315 xmlSchemaParserCtxtPtr ctxt,
8316 const xmlChar * name)
8317{
Daniel Veillard4255d502002-04-16 15:50:10 +00008318 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008319 xmlGenericError(xmlGenericErrorContext,
8320 "Found unexpected type = NULL in %s content model\n",
8321 name);
8322 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008323 }
8324 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008325 case XML_SCHEMA_TYPE_ANY: {
8326 xmlAutomataStatePtr start, end;
8327 xmlSchemaWildcardPtr wild;
8328 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008329
Daniel Veillardc0826a72004-08-10 14:17:33 +00008330 wild = type->attributeWildcard;
8331
8332 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008333 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008334 "Internal error: xmlSchemaBuildAContentModel, "
8335 "no wildcard on xsd:any.\n", NULL, NULL);
8336 return;
8337 }
8338
8339 start = ctxt->state;
8340 end = xmlAutomataNewState(ctxt->am);
8341
8342 if (type->maxOccurs == 1) {
8343 if (wild->any == 1) {
8344 /*
8345 * We need to add both transitions:
8346 *
8347 * 1. the {"*", "*"} for elements in a namespace.
8348 */
8349 ctxt->state =
8350 xmlAutomataNewTransition2(ctxt->am,
8351 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8352 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8353 /*
8354 * 2. the {"*"} for elements in no namespace.
8355 */
8356 ctxt->state =
8357 xmlAutomataNewTransition2(ctxt->am,
8358 start, NULL, BAD_CAST "*", NULL, type);
8359 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8360
8361 } else if (wild->nsSet != NULL) {
8362 ns = wild->nsSet;
8363 do {
8364 ctxt->state = start;
8365 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8366 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8367 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8368 ns = ns->next;
8369 } while (ns != NULL);
8370
8371 } else if (wild->negNsSet != NULL) {
8372 xmlAutomataStatePtr deadEnd;
8373
8374 deadEnd = xmlAutomataNewState(ctxt->am);
8375 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8376 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8377 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8378 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8379 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8380 }
8381 } else {
8382 int counter;
8383 xmlAutomataStatePtr hop;
8384 int maxOccurs =
8385 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8386 int minOccurs =
8387 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8388
8389 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8390 hop = xmlAutomataNewState(ctxt->am);
8391 if (wild->any == 1) {
8392 ctxt->state =
8393 xmlAutomataNewTransition2(ctxt->am,
8394 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8395 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8396 ctxt->state =
8397 xmlAutomataNewTransition2(ctxt->am,
8398 start, NULL, BAD_CAST "*", NULL, type);
8399 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8400 } else if (wild->nsSet != NULL) {
8401 ns = wild->nsSet;
8402 do {
8403 ctxt->state =
8404 xmlAutomataNewTransition2(ctxt->am,
8405 start, NULL, BAD_CAST "*", ns->value, type);
8406 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8407 ns = ns->next;
8408 } while (ns != NULL);
8409
8410 } else if (wild->negNsSet != NULL) {
8411 xmlAutomataStatePtr deadEnd;
8412
8413 deadEnd = xmlAutomataNewState(ctxt->am);
8414 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8415 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8416 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8417 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8418 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8419 }
8420 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8421 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8422 }
8423 if (type->minOccurs == 0) {
8424 xmlAutomataNewEpsilon(ctxt->am, start, end);
8425 }
8426 ctxt->state = end;
8427 break;
8428 }
8429 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008430 xmlAutomataStatePtr oldstate;
8431 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008432
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008433 /*
8434 * IMPORTANT: This puts element declarations
8435 * (and never element decl. references) into the
8436 * automaton. This is crucial and should not be changed,
8437 * since validating functions rely now on it.
8438 */
8439 particle = (xmlSchemaElementPtr) type;
8440 if (particle->ref != NULL) {
8441 if (particle->refDecl == NULL) {
8442 /*
8443 * Skip content model creation if the reference
8444 * did not resolve to a declaration.
8445 */
8446 break;
8447 } else {
8448 /*
8449 * Referenced global element declaration.
8450 */
8451 elemDecl = particle->refDecl;
8452 }
8453 } else {
8454 /*
8455 * Anonymous element declaration.
8456 */
8457 elemDecl = particle;
8458 }
8459
8460 oldstate = ctxt->state;
8461
8462 if (particle->maxOccurs >= UNBOUNDED) {
8463 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008464 xmlAutomataStatePtr tmp;
8465 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008466
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008467 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008468 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008469 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008470 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008471 particle->minOccurs - 1, UNBOUNDED);
8472 ctxt->state =
8473 xmlAutomataNewTransition2(ctxt->am,
8474 ctxt->state, NULL,
8475 elemDecl->name,
8476 elemDecl->targetNamespace,
8477 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008478 tmp = ctxt->state;
8479 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008480 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008481 ctxt->state =
8482 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008483 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008484
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008485 } else {
8486 ctxt->state =
8487 xmlAutomataNewTransition2(ctxt->am,
8488 ctxt->state, NULL,
8489 elemDecl->name,
8490 elemDecl->targetNamespace,
8491 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008492 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8493 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008494 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008495 /* basically an elem* */
8496 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8497 ctxt->state);
8498 }
8499 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008500 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008501 xmlAutomataStatePtr tmp;
8502 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008503
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008504 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8505 oldstate, NULL);
8506 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008507 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008508 particle->minOccurs - 1,
8509 particle->maxOccurs - 1);
8510 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8511 ctxt->state,
8512 NULL,
8513 elemDecl->name,
8514 elemDecl->targetNamespace,
8515 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008516 tmp = ctxt->state;
8517 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008518 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008519 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008520 NULL, counter);
8521 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008522 /* basically an elem? */
8523 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008524 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008525 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008526
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008527 } else {
8528 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8529 ctxt->state,
8530 NULL,
8531 elemDecl->name,
8532 elemDecl->targetNamespace,
8533 (xmlSchemaTypePtr) elemDecl);
8534 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008535 /* basically an elem? */
8536 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008537 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008538 }
8539 }
8540 break;
8541 }
8542 case XML_SCHEMA_TYPE_SEQUENCE:{
8543 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008544
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008545 /*
8546 * If max and min occurances are default (1) then
8547 * simply iterate over the subtypes
8548 */
8549 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8550 subtypes = type->subtypes;
8551 while (subtypes != NULL) {
8552 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8553 subtypes = subtypes->next;
8554 }
8555 } else {
8556 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008557
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008558 if (type->maxOccurs >= UNBOUNDED) {
8559 if (type->minOccurs > 1) {
8560 xmlAutomataStatePtr tmp;
8561 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008562
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008563 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8564 oldstate,
8565 NULL);
8566 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008567
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008568 counter = xmlAutomataNewCounter(ctxt->am,
8569 type->
8570 minOccurs - 1,
8571 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008572
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008573 subtypes = type->subtypes;
8574 while (subtypes != NULL) {
8575 xmlSchemaBuildAContentModel(subtypes, ctxt,
8576 name);
8577 subtypes = subtypes->next;
8578 }
8579 tmp = ctxt->state;
8580 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8581 oldstate, counter);
8582 ctxt->state =
8583 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8584 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008585
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008586 } else {
8587 subtypes = type->subtypes;
8588 while (subtypes != NULL) {
8589 xmlSchemaBuildAContentModel(subtypes, ctxt,
8590 name);
8591 subtypes = subtypes->next;
8592 }
8593 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8594 oldstate);
8595 if (type->minOccurs == 0) {
8596 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8597 ctxt->state);
8598 }
8599 }
8600 } else if ((type->maxOccurs > 1)
8601 || (type->minOccurs > 1)) {
8602 xmlAutomataStatePtr tmp;
8603 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008604
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008605 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8606 oldstate,
8607 NULL);
8608 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008609
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008610 counter = xmlAutomataNewCounter(ctxt->am,
8611 type->minOccurs -
8612 1,
8613 type->maxOccurs -
8614 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008615
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008616 subtypes = type->subtypes;
8617 while (subtypes != NULL) {
8618 xmlSchemaBuildAContentModel(subtypes, ctxt,
8619 name);
8620 subtypes = subtypes->next;
8621 }
8622 tmp = ctxt->state;
8623 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8624 counter);
8625 ctxt->state =
8626 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8627 counter);
8628 if (type->minOccurs == 0) {
8629 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8630 ctxt->state);
8631 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008632
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008633 } else {
8634 subtypes = type->subtypes;
8635 while (subtypes != NULL) {
8636 xmlSchemaBuildAContentModel(subtypes, ctxt,
8637 name);
8638 subtypes = subtypes->next;
8639 }
8640 if (type->minOccurs == 0) {
8641 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8642 ctxt->state);
8643 }
8644 }
8645 }
8646 break;
8647 }
8648 case XML_SCHEMA_TYPE_CHOICE:{
8649 xmlSchemaTypePtr subtypes;
8650 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008651
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008652 start = ctxt->state;
8653 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008654
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008655 /*
8656 * iterate over the subtypes and remerge the end with an
8657 * epsilon transition
8658 */
8659 if (type->maxOccurs == 1) {
8660 subtypes = type->subtypes;
8661 while (subtypes != NULL) {
8662 ctxt->state = start;
8663 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8664 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8665 subtypes = subtypes->next;
8666 }
8667 } else {
8668 int counter;
8669 xmlAutomataStatePtr hop;
8670 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8671 UNBOUNDED : type->maxOccurs - 1;
8672 int minOccurs =
8673 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008674
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008675 /*
8676 * use a counter to keep track of the number of transtions
8677 * which went through the choice.
8678 */
8679 counter =
8680 xmlAutomataNewCounter(ctxt->am, minOccurs,
8681 maxOccurs);
8682 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008683
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008684 subtypes = type->subtypes;
8685 while (subtypes != NULL) {
8686 ctxt->state = start;
8687 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8688 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8689 subtypes = subtypes->next;
8690 }
8691 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8692 counter);
8693 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8694 counter);
8695 }
8696 if (type->minOccurs == 0) {
8697 xmlAutomataNewEpsilon(ctxt->am, start, end);
8698 }
8699 ctxt->state = end;
8700 break;
8701 }
8702 case XML_SCHEMA_TYPE_ALL:{
8703 xmlAutomataStatePtr start;
8704 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008705
Daniel Veillard3646d642004-06-02 19:19:14 +00008706 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008707 int lax;
8708
8709 subtypes = type->subtypes;
8710 if (subtypes == NULL)
8711 break;
8712 start = ctxt->state;
8713 while (subtypes != NULL) {
8714 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008715 /*
8716 * the following 'if' was needed to fix bug 139897
8717 * not quite sure why it only needs to be done for
8718 * elements with a 'ref', but it seems to work ok.
8719 */
8720 if (subtypes->ref != NULL)
8721 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008722 elem = (xmlSchemaElementPtr) subtypes;
8723 /*
8724 * NOTE: The {max occurs} of all the particles in the
8725 * {particles} of the group must be 0 or 1.
8726 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008727 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008728 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8729 ctxt->state,
8730 elem->name,
8731 elem->targetNamespace,
8732 1, 1, subtypes);
8733 } else if ((elem->minOccurs == 0) &&
8734 (elem->maxOccurs == 1)) {
8735
8736 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8737 ctxt->state,
8738 elem->name,
8739 elem->targetNamespace,
8740 0,
8741 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008742 subtypes);
8743 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008744 /*
8745 * NOTE: if maxOccurs == 0 then no transition will be
8746 * created.
8747 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008748 subtypes = subtypes->next;
8749 }
8750 lax = type->minOccurs == 0;
8751 ctxt->state =
8752 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8753 lax);
8754 break;
8755 }
8756 case XML_SCHEMA_TYPE_RESTRICTION:
8757 if (type->subtypes != NULL)
8758 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8759 break;
8760 case XML_SCHEMA_TYPE_EXTENSION:
8761 if (type->baseType != NULL) {
8762 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008763
8764 /*
8765 * TODO: Circular definitions will be checked at the
8766 * constraint level. So remove this when the complex type
8767 * constraints are implemented.
8768 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008769 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008770 /* TODO: Change the error code. */
8771 xmlSchemaPCustomErr(ctxt,
8772 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8773 NULL, type, type->node,
8774 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008775 return;
8776 }
8777 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008778 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008779 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008780 subtypes = type->subtypes;
8781 while (subtypes != NULL) {
8782 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8783 subtypes = subtypes->next;
8784 }
8785 } else if (type->subtypes != NULL)
8786 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8787 break;
8788 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008789 /*
8790 * Handle model group definition references.
8791 * NOTE: type->subtypes is the referenced model grop definition;
8792 * and type->subtypes->subtypes is the model group (i.e. <all> or
8793 * <choice> or <sequence>).
8794 */
8795 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8796 (type->subtypes->subtypes != NULL)) {
8797 xmlSchemaTypePtr modelGr;
8798 xmlAutomataStatePtr start, end;
8799
8800 modelGr = type->subtypes->subtypes;
8801 start = ctxt->state;
8802 end = xmlAutomataNewState(ctxt->am);
8803 if (type->maxOccurs == 1) {
8804 ctxt->state = start;
8805 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8806 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8807 } else {
8808 int counter;
8809 xmlAutomataStatePtr hop;
8810 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8811 UNBOUNDED : type->maxOccurs - 1;
8812 int minOccurs =
8813 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8814
8815 counter =
8816 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8817 hop = xmlAutomataNewState(ctxt->am);
8818 ctxt->state = start;
8819 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8820 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8821 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8822 counter);
8823 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8824 counter);
8825 }
8826 if (type->minOccurs == 0) {
8827 xmlAutomataNewEpsilon(ctxt->am, start, end);
8828 }
8829 ctxt->state = end;
8830 break;
8831 }
8832 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008833 case XML_SCHEMA_TYPE_COMPLEX:
8834 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8835 if (type->subtypes != NULL)
8836 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8837 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008838 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8839 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008840 default:
8841 xmlGenericError(xmlGenericErrorContext,
8842 "Found unexpected type %d in %s content model\n",
8843 type->type, name);
8844 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008845 }
8846}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008847
Daniel Veillard4255d502002-04-16 15:50:10 +00008848/**
8849 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008850 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00008851 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008852 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008853 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008854 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00008855 */
8856static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008857xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008858 xmlSchemaParserCtxtPtr ctxt,
8859 const xmlChar * name)
8860{
Daniel Veillard4255d502002-04-16 15:50:10 +00008861 xmlAutomataStatePtr start;
8862
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008863 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
8864 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8865 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
8866 (type->contModel != NULL))
8867 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008868
8869#ifdef DEBUG_CONTENT
8870 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008871 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008872#endif
8873
Daniel Veillard4255d502002-04-16 15:50:10 +00008874 ctxt->am = xmlNewAutomata();
8875 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008876 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008877 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008878 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008879 }
8880 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008881 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008882 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008883 type->contModel = xmlAutomataCompile(ctxt->am);
8884 if (type->contModel == NULL) {
8885 xmlSchemaPCustomErr(ctxt,
8886 XML_SCHEMAP_INTERNAL,
8887 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008888 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008889 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008890 xmlSchemaPCustomErr(ctxt,
8891 XML_SCHEMAP_NOT_DETERMINISTIC,
8892 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008893 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008894 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008895 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008896#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008897 xmlGenericError(xmlGenericErrorContext,
8898 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008899 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008900#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008901 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008902 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008903 xmlFreeAutomata(ctxt->am);
8904 ctxt->am = NULL;
8905}
8906
8907/**
8908 * xmlSchemaRefFixupCallback:
8909 * @elem: the schema element context
8910 * @ctxt: the schema parser context
8911 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008912 * Resolves the references of an element declaration
8913 * or particle, which has an element declaration as it's
8914 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008915 */
8916static void
8917xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008918 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008919 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008920 const xmlChar * context ATTRIBUTE_UNUSED,
8921 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008922{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008923 if ((ctxt == NULL) || (elem == NULL) ||
8924 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008925 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008926 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008927 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008928 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008929
Daniel Veillardc0826a72004-08-10 14:17:33 +00008930 /*
8931 * TODO: Evaluate, what errors could occur if the declaration is not
8932 * found. It might be possible that the "typefixup" might crash if
8933 * no ref declaration was found.
8934 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008935 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008936 if (elemDecl == NULL) {
8937 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008938 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008939 NULL, (xmlSchemaTypePtr) elem, elem->node,
8940 "ref", elem->ref, elem->refNs,
8941 XML_SCHEMA_TYPE_ELEMENT, NULL);
8942 } else
8943 elem->refDecl = elemDecl;
8944 } else {
8945 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8946 xmlSchemaTypePtr type;
8947
8948 /* (type definition) ... otherwise the type definition ·resolved·
8949 * to by the ·actual value· of the type [attribute] ...
8950 */
8951 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8952 elem->namedTypeNs);
8953 if (type == NULL) {
8954 xmlSchemaPResCompAttrErr(ctxt,
8955 XML_SCHEMAP_SRC_RESOLVE,
8956 NULL, (xmlSchemaTypePtr) elem, elem->node,
8957 "type", elem->namedType, elem->namedTypeNs,
8958 XML_SCHEMA_TYPE_BASIC, "type definition");
8959 } else
8960 elem->subtypes = type;
8961 }
8962 if (elem->substGroup != NULL) {
8963 xmlSchemaElementPtr substHead;
8964
8965 /*
8966 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8967 * substitutionGroup?
8968 */
8969 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008970 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008971 if (substHead == NULL) {
8972 xmlSchemaPResCompAttrErr(ctxt,
8973 XML_SCHEMAP_SRC_RESOLVE,
8974 NULL, (xmlSchemaTypePtr) elem, NULL,
8975 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8976 XML_SCHEMA_TYPE_ELEMENT, NULL);
8977 } else {
8978 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
8979 /*
8980 * (type definition)...otherwise the {type definition} of the
8981 * element declaration ·resolved· to by the ·actual value· of
8982 * the substitutionGroup [attribute], if present
8983 */
8984 if (elem->subtypes == NULL)
8985 elem->subtypes = substHead->subtypes;
8986 }
8987 }
8988 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
8989 (elem->substGroup == NULL))
8990 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8991 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008992}
8993
William M. Bracke7091952004-05-11 15:09:58 +00008994/**
8995 * xmlSchemaParseListRefFixup:
8996 * @type: the schema type definition
8997 * @ctxt: the schema parser context
8998 *
8999 * Fixup of the itemType reference of the list type.
9000 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009001static void
William M. Bracke7091952004-05-11 15:09:58 +00009002xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009003{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009004
Daniel Veillard01fa6152004-06-29 17:04:39 +00009005 if (((type->base == NULL) &&
9006 (type->subtypes == NULL)) ||
9007 ((type->base != NULL) &&
9008 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009009 /*
9010 * src-list-itemType-or-simpleType
9011 * Either the itemType [attribute] or the <simpleType> [child] of
9012 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009013 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009014 /*
9015 * TODO: Move this to the parse function.
9016 */
9017 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009018 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009019 NULL, type, type->node,
9020 "The attribute 'itemType' and the <simpleType> child "
9021 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009022 } else if (type->base!= NULL) {
9023 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9024 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009025 xmlSchemaPResCompAttrErr(ctxt,
9026 XML_SCHEMAP_SRC_RESOLVE,
9027 NULL, type, type->node,
9028 "itemType", type->base, type->baseNs,
9029 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009030 }
9031 }
9032 if ((type->subtypes != NULL) &&
9033 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9034 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009035}
9036
9037/**
9038 * xmlSchemaParseUnionRefCheck:
9039 * @typeDecl: the schema type definition
9040 * @ctxt: the schema parser context
9041 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009042 * Checks and builds the memberTypes of the union type.
9043 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009044 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009045static int
William M. Bracke7091952004-05-11 15:09:58 +00009046xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009047 xmlSchemaParserCtxtPtr ctxt)
9048{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009049
Daniel Veillard01fa6152004-06-29 17:04:39 +00009050 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9051 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009052
Daniel Veillard01fa6152004-06-29 17:04:39 +00009053 /* 1 If the <union> alternative is chosen, then [Definition:]
9054 * define the explicit members as the type definitions ·resolved·
9055 * to by the items in the ·actual value· of the memberTypes [attribute],
9056 * if any, followed by the type definitions corresponding to the
9057 * <simpleType>s among the [children] of <union>, if any.
9058 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009059
Daniel Veillard01fa6152004-06-29 17:04:39 +00009060 if (type->type != XML_SCHEMA_TYPE_UNION)
9061 return (-1);
9062 if (ctxt->ctxtType == NULL) {
9063 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009064 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009065 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9066 "available", NULL, NULL);
9067 return (-1);
9068 }
9069 /*
9070 * src-union-memberTypes-or-simpleTypes
9071 * Either the memberTypes [attribute] of the <union> element must
9072 * be non-empty or there must be at least one simpleType [child].
9073 */
9074 if ((type->base == NULL) &&
9075 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009076 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009077 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009078 NULL, NULL, type->node,
9079 "Either the attribute 'memberTypes' must be non-empty "
9080 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009081 }
9082
9083 ctxtType = ctxt->ctxtType;
9084 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009085 xmlAttrPtr attr;
9086 const xmlChar *cur, *end;
9087 xmlChar *tmp;
9088 const xmlChar *localName, *uri;
9089
9090 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009091 cur = type->base;
9092 do {
9093 while (IS_BLANK_CH(*cur))
9094 cur++;
9095 end = cur;
9096 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9097 end++;
9098 if (end == cur)
9099 break;
9100 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009101 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9102 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9103 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009104 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009105 xmlSchemaPResCompAttrErr(ctxt,
9106 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9107 NULL, NULL, type->node, "memberTypes", localName, uri,
9108 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009109 } else {
9110 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9111 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9112 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9113 if (link == NULL) {
9114 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9115 return (-1);
9116 }
9117 link->type = memberType;
9118 link->next = NULL;
9119 if (lastLink == NULL)
9120 ctxtType->memberTypes = link;
9121 else
9122 lastLink->next = link;
9123 lastLink = link;
9124 }
9125 xmlFree(tmp);
9126 cur = end;
9127 } while (*cur != 0);
9128 }
9129 /*
9130 * Add local simple types,
9131 */
9132 memberType = type->subtypes;
9133 while (memberType != NULL) {
9134 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9135 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9136 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9137 if (link == NULL) {
9138 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9139 return (-1);
9140 }
9141 link->type = memberType;
9142 link->next = NULL;
9143 if (lastLink == NULL)
9144 ctxtType->memberTypes = link;
9145 else
9146 lastLink->next = link;
9147 lastLink = link;
9148 memberType = memberType->next;
9149 }
9150 /*
9151 * The actual value is then formed by replacing any union type
9152 * definition in the ·explicit members· with the members of their
9153 * {member type definitions}, in order.
9154 */
9155 link = ctxtType->memberTypes;
9156 while (link != NULL) {
9157 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9158 subLink = link->type->memberTypes;
9159 if (subLink != NULL) {
9160 link->type = subLink->type;
9161 if (subLink->next != NULL) {
9162 lastLink = link->next;
9163 subLink = subLink->next;
9164 prevLink = link;
9165 while (subLink != NULL) {
9166 newLink = (xmlSchemaTypeLinkPtr)
9167 xmlMalloc(sizeof(xmlSchemaTypeLink));
9168 if (newLink == NULL) {
9169 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9170 NULL);
9171 return (-1);
9172 }
9173 newLink->type = memberType;
9174 prevLink->next = newLink;
9175 prevLink = newLink;
9176 newLink->next = lastLink;
9177
9178 subLink = subLink->next;
9179 }
9180 }
9181 }
9182 }
9183 link = link->next;
9184 }
9185
9186 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009187}
9188
Daniel Veillard4255d502002-04-16 15:50:10 +00009189/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009190 * xmlSchemaIsDerivedFromBuiltInType:
9191 * @ctxt: the schema parser context
9192 * @type: the type definition
9193 * @valType: the value type
9194 *
9195 *
9196 * Returns 1 if the type has the given value type, or
9197 * is derived from such a type.
9198 */
William M. Brack803812b2004-06-03 02:11:24 +00009199static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009200xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9201 xmlSchemaTypePtr type, int valType)
9202{
9203 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009204 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009205 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009206 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009207 return(1);
9208 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9209 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9210 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9211 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9212 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9213 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9214 if (type->baseType != NULL)
9215 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9216 valType));
9217 } else if ((type->subtypes != NULL) &&
9218 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9219 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9220 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9221 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9222 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9223 valType));
9224 }
9225
9226 return (0);
9227}
9228
9229/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009230 * xmlSchemaIsDerivedFromBuiltInType:
9231 * @type: the simpleType definition
9232 *
9233 * Returns the primitive type of the given type or
9234 * NULL in case of error.
9235 */
9236static xmlSchemaTypePtr
9237xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9238{
9239 while (type != NULL) {
9240 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9241 return (type);
9242 type = type->baseType;
9243 }
9244
9245 return (NULL);
9246}
9247
9248
9249/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009250 * xmlSchemaBuildAttributeUsesOwned:
9251 * @ctxt: the schema parser context
9252 * @type: the complex type definition
9253 * @cur: the attribute declaration list
9254 * @lastUse: the top of the attribute use list
9255 *
9256 * Builds the attribute uses list on the given complex type.
9257 * This one is supposed to be called by
9258 * xmlSchemaBuildAttributeValidation only.
9259 */
9260static int
9261xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9262 xmlSchemaAttributePtr cur,
9263 xmlSchemaAttributeLinkPtr *uses,
9264 xmlSchemaAttributeLinkPtr *lastUse)
9265{
9266 xmlSchemaAttributeLinkPtr tmp;
9267 while (cur != NULL) {
9268 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9269 /*
9270 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9271 * to by the ·actual value·s of the ref [attribute] of the
9272 * <attributeGroup> [children], if any."
9273 */
9274 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9275 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9276 lastUse) == -1) {
9277 return (-1);
9278 }
9279 } else {
9280 /* W3C: "1 The set of attribute uses corresponding to the
9281 * <attribute> [children], if any."
9282 */
9283 tmp = (xmlSchemaAttributeLinkPtr)
9284 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9285 if (tmp == NULL) {
9286 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9287 return (-1);
9288 }
9289 tmp->attr = cur;
9290 tmp->next = NULL;
9291 if (*uses == NULL)
9292 *uses = tmp;
9293 else
9294 (*lastUse)->next = tmp;
9295 *lastUse = tmp;
9296 }
9297 cur = cur->next;
9298 }
9299 return (0);
9300}
9301
Daniel Veillard50355f02004-06-08 17:52:16 +00009302/**
9303 * xmlSchemaCloneWildcardNsConstraints:
9304 * @ctxt: the schema parser context
9305 * @dest: the destination wildcard
9306 * @source: the source wildcard
9307 *
9308 * Clones the namespace constraints of source
9309 * and assignes them to dest.
9310 * Returns -1 on internal error, 0 otherwise.
9311 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009312static int
9313xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9314 xmlSchemaWildcardPtr *dest,
9315 xmlSchemaWildcardPtr source)
9316{
9317 xmlSchemaWildcardNsPtr cur, tmp, last;
9318
9319 if ((source == NULL) || (*dest == NULL))
9320 return(-1);
9321 (*dest)->any = source->any;
9322 cur = source->nsSet;
9323 last = NULL;
9324 while (cur != NULL) {
9325 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9326 if (tmp == NULL)
9327 return(-1);
9328 tmp->value = cur->value;
9329 if (last == NULL)
9330 (*dest)->nsSet = tmp;
9331 else
9332 last->next = tmp;
9333 last = tmp;
9334 cur = cur->next;
9335 }
9336 if ((*dest)->negNsSet != NULL)
9337 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9338 if (source->negNsSet != NULL) {
9339 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9340 if ((*dest)->negNsSet == NULL)
9341 return(-1);
9342 (*dest)->negNsSet->value = source->negNsSet->value;
9343 } else
9344 (*dest)->negNsSet = NULL;
9345 return(0);
9346}
9347
Daniel Veillard50355f02004-06-08 17:52:16 +00009348/**
9349 * xmlSchemaUnionWildcards:
9350 * @ctxt: the schema parser context
9351 * @completeWild: the first wildcard
9352 * @curWild: the second wildcard
9353 *
9354 * Unions the namespace constraints of the given wildcards.
9355 * @completeWild will hold the resulting union.
9356 * Returns a positive error code on failure, -1 in case of an
9357 * internal error, 0 otherwise.
9358 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009359static int
9360xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9361 xmlSchemaWildcardPtr completeWild,
9362 xmlSchemaWildcardPtr curWild)
9363{
9364 xmlSchemaWildcardNsPtr cur, curB, tmp;
9365
9366 /*
9367 * 1 If O1 and O2 are the same value, then that value must be the
9368 * value.
9369 */
9370 if ((completeWild->any == curWild->any) &&
9371 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9372 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9373
9374 if ((completeWild->negNsSet == NULL) ||
9375 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9376
9377 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009378 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009379
9380 /*
9381 * Check equality of sets.
9382 */
9383 cur = completeWild->nsSet;
9384 while (cur != NULL) {
9385 found = 0;
9386 curB = curWild->nsSet;
9387 while (curB != NULL) {
9388 if (cur->value == curB->value) {
9389 found = 1;
9390 break;
9391 }
9392 curB = curB->next;
9393 }
9394 if (!found)
9395 break;
9396 cur = cur->next;
9397 }
9398 if (found)
9399 return(0);
9400 } else
9401 return(0);
9402 }
9403 }
9404 /*
9405 * 2 If either O1 or O2 is any, then any must be the value
9406 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009407 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009408 if (completeWild->any == 0) {
9409 completeWild->any = 1;
9410 if (completeWild->nsSet != NULL) {
9411 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9412 completeWild->nsSet = NULL;
9413 }
9414 if (completeWild->negNsSet != NULL) {
9415 xmlFree(completeWild->negNsSet);
9416 completeWild->negNsSet = NULL;
9417 }
9418 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009419 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009420 }
9421 /*
9422 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9423 * then the union of those sets must be the value.
9424 */
9425 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9426 int found;
9427 xmlSchemaWildcardNsPtr start;
9428
9429 cur = curWild->nsSet;
9430 start = completeWild->nsSet;
9431 while (cur != NULL) {
9432 found = 0;
9433 curB = start;
9434 while (curB != NULL) {
9435 if (cur->value == curB->value) {
9436 found = 1;
9437 break;
9438 }
9439 curB = curB->next;
9440 }
9441 if (!found) {
9442 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9443 if (tmp == NULL)
9444 return (-1);
9445 tmp->value = cur->value;
9446 tmp->next = completeWild->nsSet;
9447 completeWild->nsSet = tmp;
9448 }
9449 cur = cur->next;
9450 }
9451
9452 return(0);
9453 }
9454 /*
9455 * 4 If the two are negations of different values (namespace names
9456 * or ·absent·), then a pair of not and ·absent· must be the value.
9457 */
9458 if ((completeWild->negNsSet != NULL) &&
9459 (curWild->negNsSet != NULL) &&
9460 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9461 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009462
9463 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009464 }
9465 /*
9466 * 5.
9467 */
9468 if (((completeWild->negNsSet != NULL) &&
9469 (completeWild->negNsSet->value != NULL) &&
9470 (curWild->nsSet != NULL)) ||
9471 ((curWild->negNsSet != NULL) &&
9472 (curWild->negNsSet->value != NULL) &&
9473 (completeWild->nsSet != NULL))) {
9474
9475 int nsFound, absentFound = 0;
9476
9477 if (completeWild->nsSet != NULL) {
9478 cur = completeWild->nsSet;
9479 curB = curWild->negNsSet;
9480 } else {
9481 cur = curWild->nsSet;
9482 curB = completeWild->negNsSet;
9483 }
9484 nsFound = 0;
9485 while (cur != NULL) {
9486 if (cur->value == NULL)
9487 absentFound = 1;
9488 else if (cur->value == curB->value)
9489 nsFound = 1;
9490 if (nsFound && absentFound)
9491 break;
9492 cur = cur->next;
9493 }
9494
9495 if (nsFound && absentFound) {
9496 /*
9497 * 5.1 If the set S includes both the negated namespace
9498 * name and ·absent·, then any must be the value.
9499 */
9500 completeWild->any = 1;
9501 if (completeWild->nsSet != NULL) {
9502 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9503 completeWild->nsSet = NULL;
9504 }
9505 if (completeWild->negNsSet != NULL) {
9506 xmlFree(completeWild->negNsSet);
9507 completeWild->negNsSet = NULL;
9508 }
9509 } else if (nsFound && (!absentFound)) {
9510 /*
9511 * 5.2 If the set S includes the negated namespace name
9512 * but not ·absent·, then a pair of not and ·absent· must
9513 * be the value.
9514 */
9515 if (completeWild->nsSet != NULL) {
9516 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9517 completeWild->nsSet = NULL;
9518 }
9519 if (completeWild->negNsSet == NULL) {
9520 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9521 if (completeWild->negNsSet == NULL)
9522 return (-1);
9523 }
9524 completeWild->negNsSet->value = NULL;
9525 } else if ((!nsFound) && absentFound) {
9526 /*
9527 * 5.3 If the set S includes ·absent· but not the negated
9528 * namespace name, then the union is not expressible.
9529 */
9530 xmlSchemaPErr(ctxt, completeWild->node,
9531 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009532 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009533 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009534 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009535 } else if ((!nsFound) && (!absentFound)) {
9536 /*
9537 * 5.4 If the set S does not include either the negated namespace
9538 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9539 * and a namespace name must be the value.
9540 */
9541 if (completeWild->negNsSet == NULL) {
9542 if (completeWild->nsSet != NULL) {
9543 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9544 completeWild->nsSet = NULL;
9545 }
9546 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9547 if (completeWild->negNsSet == NULL)
9548 return (-1);
9549 completeWild->negNsSet->value = curWild->negNsSet->value;
9550 }
9551 }
9552 return (0);
9553 }
9554 /*
9555 * 6.
9556 */
9557 if (((completeWild->negNsSet != NULL) &&
9558 (completeWild->negNsSet->value == NULL) &&
9559 (curWild->nsSet != NULL)) ||
9560 ((curWild->negNsSet != NULL) &&
9561 (curWild->negNsSet->value == NULL) &&
9562 (completeWild->nsSet != NULL))) {
9563
9564 if (completeWild->nsSet != NULL) {
9565 cur = completeWild->nsSet;
9566 } else {
9567 cur = curWild->nsSet;
9568 }
9569 while (cur != NULL) {
9570 if (cur->value == NULL) {
9571 /*
9572 * 6.1 If the set S includes ·absent·, then any must be the
9573 * value.
9574 */
9575 completeWild->any = 1;
9576 if (completeWild->nsSet != NULL) {
9577 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9578 completeWild->nsSet = NULL;
9579 }
9580 if (completeWild->negNsSet != NULL) {
9581 xmlFree(completeWild->negNsSet);
9582 completeWild->negNsSet = NULL;
9583 }
9584 return (0);
9585 }
9586 cur = cur->next;
9587 }
9588 if (completeWild->negNsSet == NULL) {
9589 /*
9590 * 6.2 If the set S does not include ·absent·, then a pair of not
9591 * and ·absent· must be the value.
9592 */
9593 if (completeWild->nsSet != NULL) {
9594 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9595 completeWild->nsSet = NULL;
9596 }
9597 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9598 if (completeWild->negNsSet == NULL)
9599 return (-1);
9600 completeWild->negNsSet->value = NULL;
9601 }
9602 return (0);
9603 }
9604 return (0);
9605
9606}
9607
Daniel Veillard50355f02004-06-08 17:52:16 +00009608/**
9609 * xmlSchemaIntersectWildcards:
9610 * @ctxt: the schema parser context
9611 * @completeWild: the first wildcard
9612 * @curWild: the second wildcard
9613 *
9614 * Intersects the namespace constraints of the given wildcards.
9615 * @completeWild will hold the resulting intersection.
9616 * Returns a positive error code on failure, -1 in case of an
9617 * internal error, 0 otherwise.
9618 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009619static int
9620xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9621 xmlSchemaWildcardPtr completeWild,
9622 xmlSchemaWildcardPtr curWild)
9623{
William M. Brack803812b2004-06-03 02:11:24 +00009624 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009625
9626 /*
9627 * 1 If O1 and O2 are the same value, then that value must be the
9628 * value.
9629 */
9630 if ((completeWild->any == curWild->any) &&
9631 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9632 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9633
9634 if ((completeWild->negNsSet == NULL) ||
9635 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9636
9637 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009638 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009639
9640 /*
9641 * Check equality of sets.
9642 */
9643 cur = completeWild->nsSet;
9644 while (cur != NULL) {
9645 found = 0;
9646 curB = curWild->nsSet;
9647 while (curB != NULL) {
9648 if (cur->value == curB->value) {
9649 found = 1;
9650 break;
9651 }
9652 curB = curB->next;
9653 }
9654 if (!found)
9655 break;
9656 cur = cur->next;
9657 }
9658 if (found)
9659 return(0);
9660 } else
9661 return(0);
9662 }
9663 }
9664 /*
9665 * 2 If either O1 or O2 is any, then the other must be the value.
9666 */
9667 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9668 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9669 return(-1);
9670 return(0);
9671 }
9672 /*
9673 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9674 * name or ·absent·) and the other is a set of (namespace names or
9675 * ·absent·), then that set, minus the negated value if it was in
9676 * the set, minus ·absent· if it was in the set, must be the value.
9677 */
9678 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9679 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9680 const xmlChar *neg;
9681
9682 if (completeWild->nsSet == NULL) {
9683 neg = completeWild->negNsSet->value;
9684 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9685 return(-1);
9686 } else
9687 neg = curWild->negNsSet->value;
9688 /*
9689 * Remove absent and negated.
9690 */
9691 prev = NULL;
9692 cur = completeWild->nsSet;
9693 while (cur != NULL) {
9694 if (cur->value == NULL) {
9695 if (prev == NULL)
9696 completeWild->nsSet = cur->next;
9697 else
9698 prev->next = cur->next;
9699 xmlFree(cur);
9700 break;
9701 }
9702 prev = cur;
9703 cur = cur->next;
9704 }
9705 if (neg != NULL) {
9706 prev = NULL;
9707 cur = completeWild->nsSet;
9708 while (cur != NULL) {
9709 if (cur->value == neg) {
9710 if (prev == NULL)
9711 completeWild->nsSet = cur->next;
9712 else
9713 prev->next = cur->next;
9714 xmlFree(cur);
9715 break;
9716 }
9717 prev = cur;
9718 cur = cur->next;
9719 }
9720 }
9721
9722 return(0);
9723 }
9724 /*
9725 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9726 * then the intersection of those sets must be the value.
9727 */
9728 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9729 int found;
9730
9731 cur = completeWild->nsSet;
9732 prev = NULL;
9733 while (cur != NULL) {
9734 found = 0;
9735 curB = curWild->nsSet;
9736 while (curB != NULL) {
9737 if (cur->value == curB->value) {
9738 found = 1;
9739 break;
9740 }
9741 curB = curB->next;
9742 }
9743 if (!found) {
9744 if (prev == NULL)
9745 completeWild->nsSet = cur->next;
9746 else
9747 prev->next = cur->next;
9748 tmp = cur->next;
9749 xmlFree(cur);
9750 cur = tmp;
9751 continue;
9752 }
9753 prev = cur;
9754 cur = cur->next;
9755 }
9756
9757 return(0);
9758 }
9759 /* 5 If the two are negations of different namespace names,
9760 * then the intersection is not expressible
9761 */
9762 if ((completeWild->negNsSet != NULL) &&
9763 (curWild->negNsSet != NULL) &&
9764 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9765 (completeWild->negNsSet->value != NULL) &&
9766 (curWild->negNsSet->value != NULL)) {
9767
9768 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009769 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009770 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009771 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009772 }
9773 /*
9774 * 6 If the one is a negation of a namespace name and the other
9775 * is a negation of ·absent·, then the one which is the negation
9776 * of a namespace name must be the value.
9777 */
9778 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9779 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9780 (completeWild->negNsSet->value == NULL)) {
9781 completeWild->negNsSet->value = curWild->negNsSet->value;
9782 }
9783 return(0);
9784}
9785
Daniel Veillard50355f02004-06-08 17:52:16 +00009786/**
9787 * xmlSchemaIsWildcardNsConstraintSubset:
9788 * @ctxt: the schema parser context
9789 * @wildA: the first wildcard
9790 * @wildB: the second wildcard
9791 *
9792 * Returns 1 if the namespace constraint of @wildA is an intensional
9793 * subset of @wildB, 0 otherwise.
9794 */
9795static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009796xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9797 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009798{
Daniel Veillard3646d642004-06-02 19:19:14 +00009799
Daniel Veillard50355f02004-06-08 17:52:16 +00009800 /*
9801 * Schema Component Constraint: Wildcard Subset
9802 */
9803 /*
9804 * 1 super must be any.
9805 */
9806 if (wildB->any)
9807 return (1);
9808 /*
9809 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9810 * 2.2 super must be a pair of not and the same value.
9811 */
9812 if ((wildA->negNsSet != NULL) &&
9813 (wildB->negNsSet != NULL) &&
9814 (wildA->negNsSet->value == wildA->negNsSet->value))
9815 return (1);
9816 /*
9817 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9818 */
9819 if (wildA->nsSet != NULL) {
9820 /*
9821 * 3.2.1 super must be the same set or a superset thereof.
9822 */
9823 if (wildB->nsSet != NULL) {
9824 xmlSchemaWildcardNsPtr cur, curB;
9825 int found = 0;
9826
9827 cur = wildA->nsSet;
9828 while (cur != NULL) {
9829 found = 0;
9830 curB = wildB->nsSet;
9831 while (curB != NULL) {
9832 if (cur->value == curB->value) {
9833 found = 1;
9834 break;
9835 }
9836 curB = curB->next;
9837 }
9838 if (!found)
9839 return (0);
9840 cur = cur->next;
9841 }
9842 if (found)
9843 return (1);
9844 } else if (wildB->negNsSet != NULL) {
9845 xmlSchemaWildcardNsPtr cur;
9846 /*
9847 * 3.2.2 super must be a pair of not and a namespace name or
9848 * ·absent· and that value must not be in sub's set.
9849 */
9850 cur = wildA->nsSet;
9851 while (cur != NULL) {
9852 if (cur->value == wildB->negNsSet->value)
9853 return (0);
9854 cur = cur->next;
9855 }
9856 return (1);
9857 }
9858 }
9859 return (0);
9860}
9861
9862/**
9863 * xmlSchemaBuildCompleteAttributeWildcard:
9864 * @ctxt: the schema parser context
9865 * @attrs: the attribute list
9866 * @completeWild: the resulting complete wildcard
9867 *
9868 * Returns -1 in case of an internal error, 0 otherwise.
9869 */
9870static int
9871xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9872 xmlSchemaAttributePtr attrs,
9873 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009874{
9875 while (attrs != NULL) {
9876 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9877 xmlSchemaAttributeGroupPtr group;
9878
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009879 group = (xmlSchemaAttributeGroupPtr) attrs;
9880 /*
9881 * Handle attribute group references.
9882 */
9883 if (group->ref != NULL) {
9884 if (group->refItem == NULL) {
9885 /*
9886 * TODO: Should we raise a warning here?
9887 */
9888 /*
9889 * The referenced attribute group definition could not
9890 * be resolved beforehand, so skip.
9891 */
9892 attrs = attrs->next;
9893 continue;
9894 } else
9895 group = group->refItem;
9896 }
9897 /*
9898 * For every attribute group definition, an intersected wildcard
9899 * will be created (assumed that a wildcard exists on the
9900 * particular attr. gr. def. or on any contained attr. gr. def
9901 * at all).
9902 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
9903 * that the intersection will be performed only once.
9904 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009905 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9906 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009907 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9908 group->attributes, &group->attributeWildcard) == -1)
9909 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009910 }
9911 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9912 }
9913 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009914 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009915 /*
9916 * Copy the first encountered wildcard as context, except for the annotation.
9917 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009918 *completeWild = xmlSchemaAddWildcard(ctxt);
9919 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9920 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9921 completeWild, group->attributeWildcard) == -1)
9922 return (-1);
9923 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009924 /*
9925 * Although the complete wildcard might not correspond to any
9926 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009927 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +00009928 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009929 (*completeWild)->node = group->attributeWildcard->node;
9930
9931 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9932 xmlSchemaFreeWildcard(*completeWild);
9933 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009934 }
9935 }
9936 }
9937 attrs = attrs->next;
9938 }
9939
Daniel Veillard50355f02004-06-08 17:52:16 +00009940 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009941}
9942
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009943static int
9944xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
9945 int *fixed,
9946 const xmlChar **value,
9947 xmlSchemaValPtr *val)
9948{
9949 *fixed = 0;
9950 *value = NULL;
9951 if (val != 0)
9952 *val = NULL;
9953
9954 if (item->defValue == NULL)
9955 item = item->refDecl;
9956
9957 if (item == NULL)
9958 return (0);
9959
9960 if (item->defValue != NULL) {
9961 *value = item->defValue;
9962 if (val != 0)
9963 *val = item->defVal;
9964 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
9965 *fixed = 1;
9966 return (1);
9967 }
9968 return (0);
9969}
Daniel Veillard3646d642004-06-02 19:19:14 +00009970/**
9971 * xmlSchemaMatchesWildcardNs:
9972 * @wild: the wildcard
9973 * @ns: the namespace
9974 *
9975 *
9976 * Returns 1 if the given namespace matches the wildcard,
9977 * 0 otherwise.
9978 */
9979static int
9980xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
9981{
9982 if (wild == NULL)
9983 return(0);
9984
9985 if (wild->any)
9986 return(1);
9987 else if (wild->nsSet != NULL) {
9988 xmlSchemaWildcardNsPtr cur;
9989
9990 cur = wild->nsSet;
9991 while (cur != NULL) {
9992 if (xmlStrEqual(cur->value, ns))
9993 return(1);
9994 cur = cur->next;
9995 }
9996 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
9997 (!xmlStrEqual(wild->negNsSet->value, ns)))
9998 return(1);
9999
10000 return(0);
10001}
10002
10003/**
10004 * xmlSchemaBuildAttributeValidation:
10005 * @ctxt: the schema parser context
10006 * @type: the complex type definition
10007 *
10008 *
10009 * Builds the wildcard and the attribute uses on the given complex type.
10010 * Returns -1 if an internal error occurs, 0 otherwise.
10011 */
10012static int
10013xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10014{
10015 xmlSchemaTypePtr baseType = NULL;
10016 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010017 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010018 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010019 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010020 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010021 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010022 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010023
Daniel Veillard01fa6152004-06-29 17:04:39 +000010024 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010025 /*
10026 * Complex Type Definition with complex content Schema Component.
10027 *
10028 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010029 * TODO: Add checks for absent referenced attribute declarations and
10030 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010031 */
10032 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010033 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010034 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010035 "attribute uses already builded.\n",
10036 NULL, NULL);
10037 return (-1);
10038 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010039 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010040 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010041 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010042 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010043 type->name, NULL);
10044 return (-1);
10045 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010046 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010047 if (baseType == anyType)
10048 baseIsAnyType = 1;
10049 /*
10050 * Inherit the attribute uses of the base type.
10051 */
10052 /*
10053 * NOTE: It is allowed to "extend" the anyType complex type.
10054 */
10055 if (!baseIsAnyType) {
10056 if (baseType != NULL) {
10057 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10058 tmp = (xmlSchemaAttributeLinkPtr)
10059 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10060 if (tmp == NULL) {
10061 xmlSchemaPErrMemory(ctxt,
10062 "building attribute uses of complexType", NULL);
10063 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010064 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010065 tmp->attr = cur->attr;
10066 tmp->next = NULL;
10067 if (type->attributeUses == NULL) {
10068 type->attributeUses = tmp;
10069 } else
10070 lastBaseUse->next = tmp;
10071 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010072 }
10073 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010074 }
10075 if ((type->subtypes != NULL) &&
10076 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10077 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010078 /*
10079 * type --> (<simpleContent>|<complexContent>)
10080 * --> (<restriction>|<extension>) --> attributes
10081 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010082 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010083 } else {
10084 /* Short hand form of the complexType. */
10085 attrs = type->attributes;
10086 }
10087 /*
10088 * Handle attribute wildcards.
10089 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010090 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10091 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010092 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010093 * NOTE: During the parse time, the wildcard is created on the complexType
10094 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010095 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010096 if (err == -1) {
10097 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10098 "Internal error: xmlSchemaBuildAttributeValidation: "
10099 "failed to build an intersected attribute wildcard.\n",
10100 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010101 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010102 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010103
10104 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10105 ((baseIsAnyType) ||
10106 ((baseType != NULL) &&
10107 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10108 (baseType->attributeWildcard != NULL)))) {
10109 if (type->attributeWildcard != NULL) {
10110 /*
10111 * Union the complete wildcard with the base wildcard.
10112 */
10113 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10114 baseType->attributeWildcard) == -1)
10115 return (-1);
10116 } else {
10117 /*
10118 * Just inherit the wildcard.
10119 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010120 /*
10121 * NOTE: This is the only case where an attribute
10122 * wildcard is shared.
10123 */
10124 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10125 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010126 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010127 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010128 }
10129
10130 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10131 if (type->attributeWildcard != NULL) {
10132 /*
10133 * Derivation Valid (Restriction, Complex)
10134 * 4.1 The {base type definition} must also have one.
10135 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010136 if (baseType->attributeWildcard == NULL) {
10137 xmlSchemaPCustomErr(ctxt,
10138 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10139 NULL, type, NULL,
10140 "The type has an attribute wildcard, "
10141 "but the base type %s does not have one",
10142 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10143 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010144 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010145 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010146 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10147 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010148 xmlSchemaPCustomErr(ctxt,
10149 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10150 NULL, type, NULL,
10151 "The attribute wildcard is not a valid "
10152 "subset of the wildcard in the base type %s",
10153 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10154 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010155 return (1);
10156 }
10157 /* 4.3 Unless the {base type definition} is the ·ur-type
10158 * definition·, the complex type definition's {attribute
10159 * wildcard}'s {process contents} must be identical to or
10160 * stronger than the {base type definition}'s {attribute
10161 * wildcard}'s {process contents}, where strict is stronger
10162 * than lax is stronger than skip.
10163 */
10164 if ((type->baseType != anyType) &&
10165 (type->attributeWildcard->processContents <
10166 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010167 xmlSchemaPCustomErr(ctxt,
10168 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10169 NULL, type, NULL,
10170 "The 'process contents' of the attribute wildcard is weaker than "
10171 "the one in the base type %s",
10172 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10173 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010174 return (1);
10175 }
10176 }
10177 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10178 /*
10179 * Derivation Valid (Extension)
10180 * At this point the type and the base have both, either
10181 * no wildcard or a wildcard.
10182 */
10183 if ((baseType->attributeWildcard != NULL) &&
10184 (baseType->attributeWildcard != type->attributeWildcard)) {
10185 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010186 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010187 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010188 xmlSchemaPCustomErr(ctxt,
10189 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10190 NULL, type, NULL,
10191 "The attribute wildcard is not a valid "
10192 "superset of the one in the base type %s",
10193 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10194 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010195 return (1);
10196 }
10197 }
10198 }
10199
Daniel Veillard3646d642004-06-02 19:19:14 +000010200 /*
10201 * Gather attribute uses defined by this type.
10202 */
10203 if (attrs != NULL) {
10204 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10205 &uses, &lastUse) == -1) {
10206 return (-1);
10207 }
10208 }
10209 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10210 * "Two distinct attribute declarations in the {attribute uses} must
10211 * not have identical {name}s and {target namespace}s."
10212 *
10213 * For "extension" this is done further down.
10214 */
10215 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10216 cur = uses;
10217 while (cur != NULL) {
10218 tmp = cur->next;
10219 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010220 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10221 xmlSchemaGetAttrName(tmp->attr))) &&
10222 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10223 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10224
10225 xmlSchemaPAttrUseErr(ctxt,
10226 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10227 NULL, type, NULL, cur->attr,
10228 "Duplicate attribute use %s specified",
10229 xmlSchemaFormatNsUriLocal(&str,
10230 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10231 xmlSchemaGetAttrName(tmp->attr))
10232 );
10233 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010234 break;
10235 }
10236 tmp = tmp->next;
10237 }
10238 cur = cur->next;
10239 }
10240 }
10241 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10242 /*
10243 * Derive by restriction.
10244 */
10245 if (baseIsAnyType) {
10246 type->attributeUses = uses;
10247 } else {
10248 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010249 const xmlChar *bEffValue;
10250 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010251
10252 cur = uses;
10253 while (cur != NULL) {
10254 found = 0;
10255 base = type->attributeUses;
10256 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010257 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10258 xmlSchemaGetAttrName(base->attr)) &&
10259 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10260 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010261
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010262 found = 1;
10263
Daniel Veillard3646d642004-06-02 19:19:14 +000010264 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10265 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10266 /*
10267 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010268 */
10269 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010270 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010271 NULL, type, NULL, cur->attr,
10272 "The 'optional' use is inconsistent with a matching "
10273 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010274 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10275 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10276 /*
10277 * derivation-ok-restriction 3
10278 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010279 xmlSchemaPCustomErr(ctxt,
10280 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10281 NULL, type, NULL,
10282 "A matching attribute use for the 'required' "
10283 "attribute use %s of the base type is missing",
10284 xmlSchemaFormatNsUriLocal(&str,
10285 xmlSchemaGetAttrTargetNsURI(base->attr),
10286 xmlSchemaGetAttrName(base->attr)));
10287 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010288 } else {
10289 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010290 * 2.1.3 [Definition:] Let the effective value
10291 * constraint of an attribute use be its {value
10292 * constraint}, if present, otherwise its {attribute
10293 * declaration}'s {value constraint} .
10294 */
10295 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10296 &bEffValue, 0);
10297 /*
10298 * 2.1.3 ... one of the following must be true
10299 *
10300 * 2.1.3.1 B's ·effective value constraint· is
10301 * ·absent· or default.
10302 */
10303 if ((bEffValue != NULL) &&
10304 (effFixed == 1)) {
10305 const xmlChar *rEffValue = NULL;
10306
10307 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10308 &rEffValue, 0);
10309 /*
10310 * 2.1.3.2 R's ·effective value constraint· is
10311 * fixed with the same string as B's.
10312 */
10313 if ((effFixed == 0) ||
10314 (! xmlStrEqual(rEffValue, bEffValue))) {
10315 xmlSchemaPAttrUseErr(ctxt,
10316 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10317 NULL, type, NULL, cur->attr,
10318 "The effective value constraint of the "
10319 "attribute use is inconsistent with "
10320 "its correspondent of the base type",
10321 NULL);
10322 }
10323 }
10324 /*
10325 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10326 */
10327 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010328 * Override the attribute use.
10329 */
10330 base->attr = cur->attr;
10331 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010332
Daniel Veillard3646d642004-06-02 19:19:14 +000010333 break;
10334 }
10335 base = base->next;
10336 }
10337
10338 if (!found) {
10339 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10340 /*
10341 * derivation-ok-restriction 2.2
10342 */
10343 if ((type->attributeWildcard != NULL) &&
10344 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10345 cur->attr->targetNamespace))
10346 found = 1;
10347
10348 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010349 xmlSchemaPAttrUseErr(ctxt,
10350 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10351 NULL, type, NULL, cur->attr,
10352 "Neither a matching attribute use, "
10353 "nor a matching wildcard in the base type does exist",
10354 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010355 } else {
10356 /*
10357 * Add the attribute use.
10358 *
10359 * Note that this may lead to funny derivation error reports, if
10360 * multiple equal attribute uses exist; but this is not
10361 * allowed anyway, and it will be reported beforehand.
10362 */
10363 tmp = cur;
10364 if (prev != NULL)
10365 prev->next = cur->next;
10366 else
10367 uses = cur->next;
10368 cur = cur->next;
10369 if (type->attributeUses == NULL) {
10370 type->attributeUses = tmp;
10371 } else
10372 lastBaseUse->next = tmp;
10373 lastBaseUse = tmp;
10374
10375 continue;
10376 }
10377 }
10378 }
10379 prev = cur;
10380 cur = cur->next;
10381 }
10382 if (uses != NULL)
10383 xmlSchemaFreeAttributeUseList(uses);
10384 }
10385 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10386 /*
10387 * The spec allows only appending, and not other kinds of extensions.
10388 *
10389 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10390 */
10391 if (uses != NULL) {
10392 if (type->attributeUses == NULL) {
10393 type->attributeUses = uses;
10394 } else
10395 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010396 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010397 } else {
10398 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010399 * Derive implicitely from the ur-type.
10400 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010401 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010402 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010403 /*
10404 * 3.4.6 -> Complex Type Definition Properties Correct
10405 */
10406 if (type->attributeUses != NULL) {
10407 cur = type->attributeUses;
10408 prev = NULL;
10409 while (cur != NULL) {
10410 /*
10411 * 4. Two distinct attribute declarations in the {attribute uses} must
10412 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010413 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010414 * Note that this was already done for "restriction" and types derived from
10415 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010416 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010417 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10418 tmp = cur->next;
10419 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010420 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10421 xmlSchemaGetAttrName(tmp->attr))) &&
10422 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10423 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010424
Daniel Veillardc0826a72004-08-10 14:17:33 +000010425 xmlSchemaPAttrUseErr(ctxt,
10426 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10427 NULL, type, NULL, tmp->attr,
10428 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010429 break;
10430 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010431 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010432 }
10433 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010434 /*
10435 * 5. Two distinct attribute declarations in the {attribute uses} must
10436 * not have {type definition}s which are or are derived from ID.
10437 */
10438 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010439 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010440 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010441 xmlSchemaPAttrUseErr(ctxt,
10442 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10443 NULL, type, NULL, cur->attr,
10444 "There must not exist more than one attribute use, "
10445 "declared of type 'ID' or derived from it",
10446 NULL);
10447 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010448 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010449 id = cur;
10450 }
10451 /*
10452 * Remove "prohibited" attribute uses. The reason this is done at this late
10453 * stage is to be able to catch dublicate attribute uses. So we had to keep
10454 * prohibited uses in the list as well.
10455 */
10456 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10457 tmp = cur;
10458 if (prev == NULL)
10459 type->attributeUses = cur->next;
10460 else
10461 prev->next = cur->next;
10462 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010463 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010464 } else {
10465 prev = cur;
10466 cur = cur->next;
10467 }
10468 }
10469 }
10470 /*
10471 * TODO: This check should be removed if we are 100% sure of
10472 * the base type attribute uses already being built.
10473 */
10474 if ((baseType != NULL) && (!baseIsAnyType) &&
10475 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10476 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010477 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010478 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010479 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010480 baseType->name, NULL);
10481 }
10482 return (0);
10483}
10484
10485/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010486 * xmlSchemaTypeFinalContains:
10487 * @schema: the schema
10488 * @type: the type definition
10489 * @final: the final
10490 *
10491 * Evaluates if a type definition contains the given "final".
10492 * This does take "finalDefault" into account as well.
10493 *
10494 * Returns 1 if the type does containt the given "final",
10495 * 0 otherwise.
10496 */
10497static int
10498xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10499{
10500 int tfinal = final, tflags = type->flags;
10501
10502 if (type == NULL)
10503 return (0);
10504 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10505 switch (final) {
10506 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10507 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10508 break;
10509 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10510 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10511 break;
10512 case XML_SCHEMAS_TYPE_FINAL_LIST:
10513 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10514 break;
10515 case XML_SCHEMAS_TYPE_FINAL_UNION:
10516 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10517 break;
10518 }
10519 tflags = schema->flags;
10520 }
10521 if (tflags & tfinal)
10522 return (1);
10523 else
10524 return (0);
10525
10526}
10527
10528/**
10529 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10530 * @type: the Union Simple Type
10531 *
10532 * Returns a list of member types of @type if existing,
10533 * returns NULL otherwise.
10534 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010535static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010536xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10537{
10538 while (type != NULL) {
10539 if (type->memberTypes != NULL)
10540 return (type->memberTypes);
10541 else
10542 type = type->baseType;
10543 }
10544 return (NULL);
10545}
10546
10547/**
10548 * xmlSchemaGetListSimpleTypeItemType:
10549 * @type: the simple type definition
10550 *
10551 * Returns the item type definition of the list simple type.
10552 */
10553static xmlSchemaTypePtr
10554xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10555{
10556 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10557 return (NULL);
10558 /*
10559 * Note: In libxml2, the built-in types do not reflect
10560 * the datatype hierarchy (yet?) - we have to treat them
10561 * in a special way.
10562 */
10563 if (type->type == XML_SCHEMA_TYPE_BASIC)
10564 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10565 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10566 /* 1 If the <list> alternative is chosen, then the type
10567 * definition ·resolved· to by the ·actual value· of the
10568 * itemType [attribute] of <list>, if present, otherwise
10569 * the type definition corresponding to the <simpleType>
10570 * among the [children] of <list>.
10571 */
10572 return (type->subtypes->subtypes);
10573 else {
10574 /* 2 If the <restriction> option is chosen, then the
10575 * {item type definition} of the {base type definition}.
10576 */
10577 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10578 }
10579}
10580
10581/**
10582 * xmlSchemaCheckCOSSTDerivedOK:
10583 * @type: the derived simple type definition
10584 * @baseType: the base type definition
10585 *
10586 * Checks wheter @type can be validly
10587 * derived from @baseType.
10588 *
10589 * Returns 0 on success, an positive error code otherwise.
10590 */
10591static int
10592xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10593 xmlSchemaTypePtr type,
10594 xmlSchemaTypePtr baseType,
10595 int subset)
10596{
10597 /*
10598 * Schema Component Constraint: Type Derivation OK (Simple)
10599 *
10600 *
10601 * 1 They are the same type definition.
10602 * TODO: The identy check might have to be more complex than this.
10603 */
10604 if (type == baseType)
10605 return (0);
10606 /*
10607 * 2.1 restriction is not in the subset, or in the {final}
10608 * of its own {base type definition};
10609 */
10610 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10611 (xmlSchemaTypeFinalContains(schema,
10612 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10613 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10614 }
10615 /* 2.2 */
10616 if (type->baseType == baseType) {
10617 /*
10618 * 2.2.1 D's ·base type definition· is B.
10619 */
10620 return (0);
10621 }
10622 /*
10623 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10624 * and is validly derived from B given the subset, as defined by this
10625 * constraint.
10626 */
10627 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10628 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10629 return (0);
10630 }
10631 /*
10632 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10633 * definition·.
10634 */
10635 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10636 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10637 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10638 return (0);
10639 }
10640 /*
10641 * 2.2.4 B's {variety} is union and D is validly derived from a type
10642 * definition in B's {member type definitions} given the subset, as
10643 * defined by this constraint.
10644 *
10645 * NOTE: This seems not to involve built-in types, since there is no
10646 * built-in Union Simple Type.
10647 */
10648 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10649 xmlSchemaTypeLinkPtr cur;
10650
10651 cur = baseType->memberTypes;
10652 while (cur != NULL) {
10653 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10654 cur->type, subset) == 0)
10655 return (0);
10656 cur = cur->next;
10657 }
10658 }
10659
10660 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10661}
10662
10663
10664/**
10665 * xmlSchemaCheckSTPropsCorrect:
10666 * @ctxt: the schema parser context
10667 * @type: the simple type definition
10668 *
10669 * Checks st-props-correct.
10670 *
10671 * Returns 0 if the properties are correct,
10672 * if not, a positive error code and -1 on internal
10673 * errors.
10674 */
10675static int
10676xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10677 xmlSchemaTypePtr type)
10678{
10679 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10680 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010681 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010682
Daniel Veillardc0826a72004-08-10 14:17:33 +000010683 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010684 /*
10685 * Schema Component Constraint: Simple Type Definition Properties Correct
10686 *
10687 * NOTE: This is somehow redundant, since we actually built a simple type
10688 * to have all the needed information; this acts as an self test.
10689 */
10690 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10691 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10692 /*
10693 * TODO: 1 The values of the properties of a simple type definition must be as
10694 * described in the property tableau in Datatype definition, modulo the
10695 * impact of Missing Sub-components (§5.3).
10696 */
10697 /* Base type: If the datatype has been ·derived· by ·restriction·
10698 * then the Simple Type Definition component from which it is ·derived·,
10699 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10700 */
10701 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010702 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010703 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010704 NULL, type, NULL,
10705 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010706 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10707 }
10708 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10709 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10710 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010711 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010712 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010713 NULL, type, NULL,
10714 "The base type %s is not a simple type",
10715 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10716 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010717 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10718 }
10719 if ((baseType != anySimpleType) &&
10720 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010721 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010722 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010723 NULL, type, NULL,
10724 "A type, derived by list or union, must have"
10725 "the simple ur-type definition as base type, not %s",
10726 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10727 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010728 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10729 }
10730 /*
10731 * Variety: One of {atomic, list, union}.
10732 */
10733 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10734 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10735 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010736 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010737 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010738 NULL, type, NULL,
10739 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010740 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10741 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010742 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010743
10744 /*
10745 * 2 All simple type definitions must be derived ultimately from the ·simple
10746 * ur-type definition (so· circular definitions are disallowed). That is, it
10747 * must be possible to reach a built-in primitive datatype or the ·simple
10748 * ur-type definition· by repeatedly following the {base type definition}.
10749 */
10750 baseType = type->baseType;
10751 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10752 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10753 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10754 if (baseType == anySimpleType)
10755 break;
10756 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010757 xmlSchemaPCustomErr(ctxt,
10758 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10759 NULL, type, NULL,
10760 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010761 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10762 }
10763 baseType = baseType->baseType;
10764 }
10765 /*
10766 * 3 The {final} of the {base type definition} must not contain restriction.
10767 */
10768 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10769 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010770 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010771 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010772 NULL, type, NULL,
10773 "The 'final' of its base type %s must not contain "
10774 "'restriction'",
10775 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10776 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010777 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10778 }
10779 return (0);
10780}
10781
10782/**
10783 * xmlSchemaCheckDerivationValidSimpleRestriction:
10784 * @ctxt: the schema parser context
10785 * @type: the simple type definition
10786 *
10787 * Checks if the given @type (simpleType) is derived
10788 * validly by restriction.
10789 *
10790 * Returns -1 on internal errors, 0 if the type is validly derived,
10791 * a positive error code otherwise.
10792 */
10793static int
10794xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010795 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010796{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010797 xmlChar *str = NULL;
10798
10799 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010800
10801 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10802 xmlSchemaPErr(ctxt, type->node,
10803 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010804 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10805 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010806 type->name, NULL);
10807 return (-1);
10808 }
10809
10810 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10811 xmlSchemaTypePtr primitive;
10812 /*
10813 * 1.1 The {base type definition} must be an atomic simple
10814 * type definition or a built-in primitive datatype.
10815 */
10816 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010817 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010818 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010819 NULL, type, NULL,
10820 "The base type %s is not an atomic simple type",
10821 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10822 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010823 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10824 }
10825 /* 1.2 The {final} of the {base type definition} must not contain
10826 * restriction.
10827 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010828 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010829 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10830 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010831 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010832 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010833 NULL, type, NULL,
10834 "The final of its base type %s must not contain 'restriction'",
10835 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10836 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010837 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10838 }
10839
10840 /*
10841 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10842 * type definition}, as specified in the appropriate subsection of 3.2
10843 * Primitive datatypes.
10844 */
10845 if (type->facets != NULL) {
10846 xmlSchemaFacetPtr facet;
10847 int ok = 1;
10848
10849 primitive = xmlSchemaGetPrimitiveType(type);
10850 if (primitive == NULL) {
10851 xmlSchemaPErr(ctxt, type->node,
10852 XML_ERR_INTERNAL_ERROR,
10853 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010854 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010855 type->name, NULL);
10856 return (-1);
10857 }
10858 facet = type->facets;
10859 do {
10860 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010861 ok = 0;
10862 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010863 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010864 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010865 }
10866 facet = facet->next;
10867 } while (facet != NULL);
10868 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010869 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010870 }
10871 /*
10872 * TODO: 1.3.2 (facet derivation)
10873 */
10874 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10875 xmlSchemaTypePtr itemType = NULL;
10876
10877 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10878 if (itemType == NULL) {
10879 xmlSchemaPErr(ctxt, type->node,
10880 XML_ERR_INTERNAL_ERROR,
10881 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010882 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010883 type->name, NULL);
10884 return (-1);
10885 }
10886 /*
10887 * 2.1 The {item type definition} must have a {variety} of atomic or
10888 * union (in which case all the {member type definitions}
10889 * must be atomic).
10890 */
10891 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10892 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010893 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010894 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010895 NULL, type, NULL,
10896 "The item type %s must have a variety of atomic or union",
10897 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10898 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010899 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10900 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10901 xmlSchemaTypeLinkPtr member;
10902
10903 member = itemType->memberTypes;
10904 while (member != NULL) {
10905 if ((member->type->flags &
10906 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010907 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010908 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010909 NULL, type, NULL,
10910 "The item type is a union type, but the "
10911 "member type %s of this item type is not atomic",
10912 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10913 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010914 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10915 }
10916 member = member->next;
10917 }
10918 }
10919
10920 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10921 xmlSchemaFacetPtr facet;
10922 /*
10923 * This is the case if we have: <simpleType><list ..
10924 */
10925 /*
10926 * 2.3.1
10927 * 2.3.1.1 The {final} of the {item type definition} must not
10928 * contain list.
10929 */
10930 if (xmlSchemaTypeFinalContains(ctxt->schema,
10931 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010932 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010933 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010934 NULL, type, NULL,
10935 "The final of its item type %s must not contain 'list'",
10936 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10937 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010938 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10939 }
10940 /*
10941 * 2.3.1.2 The {facets} must only contain the whiteSpace
10942 * facet component.
10943 */
10944 if (type->facets != NULL) {
10945 facet = type->facets;
10946 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010947 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10948 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010949 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010950 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010951 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10952 }
10953 facet = facet->next;
10954 } while (facet != NULL);
10955 }
10956 /*
10957 * TODO: Datatypes states:
10958 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10959 * whose ·lexical space· allows space (such as string or anyURI)or
10960 * a ·union· datatype any of whose {member type definitions}'s
10961 * ·lexical space· allows space.
10962 */
10963 } else {
10964 /*
10965 * This is the case if we have: <simpleType><restriction ...
10966 */
10967 /*
10968 * 2.3.2
10969 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10970 */
10971 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010972 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010973 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010974 NULL, type, NULL,
10975 "The base type %s must be a list type",
10976 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10977 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010978 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
10979 }
10980 /*
10981 * 2.3.2.2 The {final} of the {base type definition} must not
10982 * contain restriction.
10983 */
10984 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10985 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010986 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010987 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010988 NULL, type, NULL,
10989 "The final of the base type %s must not contain 'restriction'",
10990 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10991 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010992 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
10993 }
10994 /*
10995 * 2.3.2.3 The {item type definition} must be validly derived
10996 * from the {base type definition}'s {item type definition} given
10997 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
10998 */
10999 {
11000 xmlSchemaTypePtr baseItemType;
11001
11002 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11003 if (baseItemType == NULL) {
11004 xmlSchemaPErr(ctxt, type->node,
11005 XML_ERR_INTERNAL_ERROR,
11006 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011007 "List simple type '%s': Failed to "
11008 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011009 type->name, type->baseType->name);
11010 return (-1);
11011 }
11012 if ((itemType != baseItemType) &&
11013 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11014 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011015 xmlChar *strBIT = NULL, *strBT = NULL;
11016 xmlSchemaPCustomErrExt(ctxt,
11017 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11018 NULL, type, NULL,
11019 "The item type %s is not validly derived from the "
11020 "item type %s of the base type %s",
11021 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11022 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11023 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11024
11025 FREE_AND_NULL(str)
11026 FREE_AND_NULL(strBIT)
11027 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011028 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11029 }
11030 }
11031
11032 if (type->facets != NULL) {
11033 xmlSchemaFacetPtr facet;
11034 int ok = 1;
11035 /*
11036 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11037 * and enumeration facet components are allowed among the {facets}.
11038 */
11039 facet = type->facets;
11040 do {
11041 switch (facet->type) {
11042 case XML_SCHEMA_FACET_LENGTH:
11043 case XML_SCHEMA_FACET_MINLENGTH:
11044 case XML_SCHEMA_FACET_MAXLENGTH:
11045 case XML_SCHEMA_FACET_WHITESPACE:
11046 /*
11047 * TODO: 2.5.1.2 List datatypes
11048 * The value of ·whiteSpace· is fixed to the value collapse.
11049 */
11050 case XML_SCHEMA_FACET_PATTERN:
11051 case XML_SCHEMA_FACET_ENUMERATION:
11052 break;
11053 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011054 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011055 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011056 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011057 /*
11058 * We could return, but it's nicer to report all
11059 * invalid facets.
11060 */
11061 ok = 0;
11062 }
11063 }
11064 facet = facet->next;
11065 } while (facet != NULL);
11066 if (ok == 0)
11067 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11068 /*
11069 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11070 * is a facet of the same kind in the {facets} of the {base type
11071 * definition} (call this BF),then the DF's {value} must be a valid
11072 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11073 */
11074 }
11075
11076
11077 }
11078 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11079 /*
11080 * 3.1 The {member type definitions} must all have {variety} of
11081 * atomic or list.
11082 */
11083 xmlSchemaTypeLinkPtr member;
11084
11085 member = type->memberTypes;
11086 while (member != NULL) {
11087 if (((member->type->flags &
11088 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11089 ((member->type->flags &
11090 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011091 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011092 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011093 NULL, type, NULL,
11094 "The member type %s is neither an atomic, nor a list type",
11095 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11096 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011097 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11098 }
11099 member = member->next;
11100 }
11101 /*
11102 * 3.3.1 If the {base type definition} is the ·simple ur-type
11103 * definition·
11104 */
11105 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11106 /*
11107 * 3.3.1.1 All of the {member type definitions} must have a
11108 * {final} which does not contain union.
11109 */
11110 member = type->memberTypes;
11111 while (member != NULL) {
11112 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11113 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011114 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011115 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 NULL, type, NULL,
11117 "The final of member type %s contains 'union'",
11118 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11119 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011120 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11121 }
11122 member = member->next;
11123 }
11124 /*
11125 * 3.3.1.2 The {facets} must be empty.
11126 */
11127 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011129 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011130 NULL, type, NULL,
11131 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011132 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11133 }
11134 } else {
11135 /*
11136 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11137 */
11138 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011140 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011141 NULL, type, NULL,
11142 "The base type %s is not a union type",
11143 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11144 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011145 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11146 }
11147 /*
11148 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11149 */
11150 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11151 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011152 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011153 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011154 NULL, type, NULL,
11155 "The final of its base type %s must not contain 'restriction'",
11156 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11157 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011158 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11159 }
11160 /*
11161 * 3.3.2.3 The {member type definitions}, in order, must be validly
11162 * derived from the corresponding type definitions in the {base
11163 * type definition}'s {member type definitions} given the empty set,
11164 * as defined in Type Derivation OK (Simple) (§3.14.6).
11165 */
11166 {
11167 xmlSchemaTypeLinkPtr baseMember;
11168
11169 /*
11170 * OPTIMIZE: if the type is restricting, it has no local defined
11171 * member types and inherits the member types of the base type;
11172 * thus a check for equality can be skipped.
11173 */
11174 /*
11175 * TODO: Even worse: I cannot see a scenario where a restricting
11176 * union simple type can have other member types as the member
11177 * types of it's base type. This check seems not necessary with
11178 * respect to the derivation process in libxml2.
11179 */
11180 if (type->memberTypes != NULL) {
11181 member = type->memberTypes;
11182 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11183 if ((member == NULL) && (baseMember != NULL)) {
11184 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011185 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011186 "Internal error: "
11187 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011188 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011189 "of member types in the base type\n",
11190 type->name, NULL);
11191 }
11192 while (member != NULL) {
11193 if (baseMember == NULL) {
11194 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011195 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011196 "Internal error: "
11197 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011198 "(3.3.2.3), union simple type '%s', unequal number "
11199 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011200 type->name, NULL);
11201 }
11202 if ((member->type != baseMember->type) &&
11203 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11204 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011205 xmlChar *strBMT = NULL, *strBT = NULL;
11206
11207 xmlSchemaPCustomErrExt(ctxt,
11208 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11209 NULL, type, NULL,
11210 "The member type %s is not validly derived from its "
11211 "corresponding member type %s of the base type %s",
11212 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11213 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11214 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11215 FREE_AND_NULL(str)
11216 FREE_AND_NULL(strBMT)
11217 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011218 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11219 }
11220 member = member->next;
11221 baseMember = baseMember->next;
11222 }
11223 }
11224 }
11225 /*
11226 * 3.3.2.4 Only pattern and enumeration facet components are
11227 * allowed among the {facets}.
11228 */
11229 if (type->facets != NULL) {
11230 xmlSchemaFacetPtr facet;
11231 int ok = 1;
11232
11233 facet = type->facets;
11234 do {
11235 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11236 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011237 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11238 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11239 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011240 ok = 0;
11241 }
11242 facet = facet->next;
11243 } while (facet != NULL);
11244 if (ok == 0)
11245 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11246
11247 }
11248 /*
11249 * TODO: 3.3.2.5 (facet derivation)
11250 */
11251 }
11252 }
11253
11254 return (0);
11255}
11256
11257/**
11258 * xmlSchemaCheckSRCSimpleType:
11259 * @ctxt: the schema parser context
11260 * @type: the simple type definition
11261 *
11262 * Checks crc-simple-type constraints.
11263 *
11264 * Returns 0 if the constraints are satisfied,
11265 * if not a positive error code and -1 on internal
11266 * errors.
11267 */
11268static int
11269xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11270 xmlSchemaTypePtr type)
11271{
11272 /*
11273 * NOTE: src-simple-type 2-4 are redundant, since the checks
11274 * were are done for the corresponding <restriction>, <list> and <union>
11275 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11276 * Maby this can be skipped in the future, if we get sure it's not needed.
11277 */
11278 if (type->subtypes == NULL) {
11279 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011280 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011281 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011282 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011283 type->name, NULL);
11284 return (-1);
11285 }
11286 /*
11287 * src-simple-type.1 The corresponding simple type definition, if any,
11288 * must satisfy the conditions set out in Constraints on Simple Type
11289 * Definition Schema Components (§3.14.6).
11290 */
11291 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11292 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11293 /*
11294 * TODO: Removed this, since it got annoying to get an
11295 * extra error report, if anything failed until now.
11296 * Enable this if needed.
11297 */
11298 /*
11299 xmlSchemaPErr(ctxt, type->node,
11300 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011301 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011302 "on simple type definitions.\n",
11303 type->name, NULL);
11304 */
11305 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11306 }
11307
11308 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11309 /*
11310 * src-simple-type.2 If the <restriction> alternative is chosen,
11311 * either it must have a base [attribute] or a <simpleType> among its
11312 * [children], but not both.
11313 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011314 /*
11315 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11316 * NOTE: This was removed, since this will be already handled
11317 * in the parse function for <restriction>.
11318 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011319 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11320 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11321 * an itemType [attribute] or a <simpleType> among its [children],
11322 * but not both.
11323 * NOTE: baseType is set to the local simple type definiton,
11324 * if existent, at parse time. This is a hack and not nice.
11325 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011326 /*
11327 * TODO: Remove this, and add the check to the parse function of <list>.
11328 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011329 if (((type->subtypes->base == NULL) &&
11330 (type->baseType == NULL)) ||
11331 ((type->subtypes->base != NULL) &&
11332 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011333 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011334 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011335 NULL, type, NULL,
11336 "Either the attribute 'itemType' or the <simpleType> child "
11337 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011338 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11339 }
11340
11341
11342 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11343 xmlSchemaTypeLinkPtr member;
11344 xmlSchemaTypePtr ancestor, anySimpleType;
11345
11346 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11347
11348 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11349 * the <union> alternative is chosen, there must not be any entries
11350 * in the memberTypes [attribute] at any depth which resolve to the
11351 * component corresponding to the <simpleType>.
11352 */
11353 member = type->memberTypes;
11354 while (member != NULL) {
11355 ancestor = member->type;
11356 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11357 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11358 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11359 if (ancestor == anySimpleType)
11360 break;
11361 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011362 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011363 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011364 NULL, type, NULL,
11365 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011366 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11367 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11368 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011369 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011370 * type as item type, which in turn has a list ST as member
11371 * type, we will assume this here as well, since this check
11372 * was not yet performed.
11373 */
11374
11375 }
11376 ancestor = ancestor->baseType;
11377 }
11378 member = member->next;
11379 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011380 }
11381
11382 return (0);
11383}
11384
William M. Brack2f2a6632004-08-20 23:09:47 +000011385#if 0 /* Not yet used code for CT schema validation */
11386static int
11387xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11388 const xmlChar * value,
11389 xmlSchemaTypePtr type,
11390 int fireErrors)
11391{
11392 int ret;
11393 /*
11394 * 3.14.4 Simple Type Definition Validation Rules
11395 * Validation Rule: String Valid
11396 */
11397 /*
11398 * 1 It is schema-valid with respect to that definition as defined
11399 * by Datatype Valid in [XML Schemas: Datatypes].
11400 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011401 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11402 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011403 return (ret);
11404 /*
11405 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11406 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11407 * the string must be a ·declared entity name·.
11408 */
11409 /*
11410 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11411 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11412 * then every whitespace-delimited substring of the string must be a ·declared
11413 * entity name·.
11414 */
11415 /*
11416 * 2.3 otherwise no further condition applies.
11417 */
11418
11419 return (0);
11420}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011421#endif
11422
William M. Brack2f2a6632004-08-20 23:09:47 +000011423
11424static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011425xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11426{
11427 if (vctxt->pctxt == NULL) {
11428 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11429 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11430 if (vctxt->pctxt == NULL) {
11431 xmlSchemaVErr(vctxt, NULL,
11432 XML_SCHEMAV_INTERNAL,
11433 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11434 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011435 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011436 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011437 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011438 /* TODO: Pass user data. */
11439 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11440 }
11441 return (0);
11442}
11443
11444static int
11445xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11446{
11447 if (ctxt->vctxt == NULL) {
11448 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11449 if (ctxt->vctxt == NULL) {
11450 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011451 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011452 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11453 "failed to create a temp. validation context.\n",
11454 NULL, NULL);
11455 return (-1);
11456 }
11457 /* TODO: Pass user data. */
11458 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11459 }
11460 return (0);
11461}
11462
11463/**
11464 * xmlSchemaCheckCOSValidDefault:
11465 * @ctxt: the schema parser context
11466 * @type: the simple type definition
11467 * @value: the default value
11468 * @node: an optional node (the holder of the value)
11469 *
11470 * Checks the "cos-valid-default" constraints.
11471 *
11472 * Returns 0 if the constraints are satisfied,
11473 * if not, a positive error code and -1 on internal
11474 * errors.
11475 */
11476static int
11477xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11478 xmlSchemaValidCtxtPtr vctxt,
11479 xmlSchemaTypePtr type,
11480 const xmlChar *value,
11481 xmlNodePtr node)
11482{
11483 int ret = 0;
11484
11485 /*
11486 * cos-valid-default:
11487 * Schema Component Constraint: Element Default Valid (Immediate)
11488 * For a string to be a valid default with respect to a type
11489 * definition the appropriate case among the following must be true:
11490 */
11491 /*
11492 * NOTE: This has to work without a given node (the holder of the
11493 * value), since it should work on the component, i.e. an underlying
11494 * DOM must not be mandatory.
11495 */
11496 if ((pctxt == NULL) || (vctxt == NULL)) {
11497 xmlSchemaPErr(pctxt, node,
11498 XML_SCHEMAP_INTERNAL,
11499 "Internal error: xmlSchemaCheckCOSValidDefault, "
11500 "bad arguments: the parser and/or validation context is "
11501 "missing.\n",
11502 NULL, NULL);
11503 return (-1);
11504 }
11505 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011506 /*
11507 * Complex type.
11508 *
11509 * 2.1 its {content type} must be a simple type definition or mixed.
11510 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011511 /*
11512 * TODO: Adjust this when the content type will be computed
11513 * correctly.
11514 */
11515 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11516 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11517 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11518 xmlSchemaPSimpleTypeErr(pctxt,
11519 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11520 NULL, NULL, node,
11521 type, NULL, NULL,
11522 "If the type of a constraint value is complex, its content "
11523 "type must be mixed or a simple type",
11524 NULL, NULL);
11525 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11526 }
11527 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011528 /*
11529 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11530 * particle must be ·emptiable· as defined by Particle Emptiable
11531 * (§3.9.6).
11532 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011533
William M. Brack2f2a6632004-08-20 23:09:47 +000011534 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011535 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011536 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011537 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011538 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011539 }
11540 /*
11541 * 1 If the type definition is a simple type definition, then the string
11542 * must be ·valid· with respect to that definition as defined by String
11543 * Valid (§3.14.4).
11544 *
11545 * AND
11546 *
11547 * 2.2.1 If the {content type} is a simple type definition, then the
11548 * string must be ·valid· with respect to that simple type definition
11549 * as defined by String Valid (§3.14.4).
11550 */
11551 vctxt->node = node;
11552 vctxt->cur = NULL;
11553 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11554 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11555 if (ret < 0) {
11556 xmlSchemaPErr(pctxt, node,
11557 /* NOTNICE: error code: This function will be used during
11558 * schema construction and xsi:type validation.
11559 */
11560 XML_SCHEMAP_INTERNAL,
11561 "Internal error: xmlSchemaCheckCOSValidDefault, "
11562 "while validating a value constaint value.\n",
11563 NULL, NULL);
11564
11565 }
11566 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011567}
11568
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011569#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011570/**
11571 * xmlSchemaGetSTContentOfCT:
11572 * @ctxt: the schema parser context
11573 * @type: the complex type definition
11574 *
11575 *
11576 * Returns the corresponding simple type for the content of
11577 * the complex type.
11578 */
11579static xmlSchemaTypePtr
11580xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11581 xmlSchemaTypePtr type)
11582{
11583 xmlSchemaTypePtr orig = type, anyType;
11584
11585 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11586 while ((type != NULL) && (type != anyType) &&
11587 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11588 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11589 return(type);
11590 type = type->baseType;
11591 }
11592 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011593 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011594 NULL, orig, NULL,
11595 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11596 "no simple type for the content of complex type '%s' could be "
11597 "computed", orig->name);
11598 return (NULL);
11599}
11600
11601
William M. Brack2f2a6632004-08-20 23:09:47 +000011602
William M. Brack2f2a6632004-08-20 23:09:47 +000011603
11604/**
11605 * xmlSchemaCheckCOSCTExtends:
11606 * @ctxt: the schema parser context
11607 * @type: the complex type definition
11608 *
11609 * Schema Component Constraint: Derivation Valid (Extension)
11610 *
11611 * Returns 0 if the constraints are satisfied, a positive
11612 * error code if not and -1 if an internal error occured.
11613 */
11614static int
11615xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11616 xmlSchemaTypePtr type)
11617{
11618 xmlSchemaTypePtr base;
11619 /*
11620 * 1 If the {base type definition} is a complex type definition,
11621 * then all of the following must be true:
11622 */
11623 base = type->baseType;
11624 if (base == NULL) {
11625 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011626 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011627 NULL, type, NULL,
11628 "Internal error: xmlSchemaCheckCOSCTExtends, "
11629 "the complex type '%s' has no base type", type->name);
11630 return (-1);
11631 }
11632 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11633 /*
11634 * 1.1 The {final} of the {base type definition} must not
11635 * contain extension.
11636 */
11637 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11638 xmlSchemaPCustomErr(ctxt,
11639 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11640 NULL, type, NULL,
11641 "The 'final' of the base type definition "
11642 "contains extension", NULL);
11643 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11644 }
11645 /*
11646 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11647 * of the complex type definition itself, that is, for every attribute
11648 * use in the {attribute uses} of the {base type definition}, there
11649 * must be an attribute use in the {attribute uses} of the complex
11650 * type definition itself whose {attribute declaration} has the same
11651 * {name}, {target namespace} and {type definition} as its attribute
11652 * declaration
11653 *
11654 * NOTE: This will be already satisfied by the way the attribute uses
11655 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11656 * is not needed.
11657 */
11658
11659 /*
11660 * 1.3 If it has an {attribute wildcard}, the complex type definition
11661 * must also have one, and the base type definition's {attribute
11662 * wildcard}'s {namespace constraint} must be a subset of the complex
11663 * type definition's {attribute wildcard}'s {namespace constraint},
11664 * as defined by Wildcard Subset (§3.10.6).
11665 *
11666 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11667 * this check is not needed.
11668 */
11669
11670 /*
11671 * 1.4 One of the following must be true:
11672 *
11673 * 1.4.1 The {content type} of the {base type definition} and the
11674 * {content type} of the complex type definition itself must be the same
11675 * simple type definition
11676 */
11677
11678
11679
11680 } else {
11681 /*
11682 * 2 If the {base type definition} is a simple type definition,
11683 * then all of the following must be true:
11684 */
11685 /*
11686 * 2.1 The {content type} must be the same simple type definition.
11687 */
11688 /*
11689 * 2.2 The {final} of the {base type definition} must not contain
11690 * extension
11691 */
11692 }
11693
11694}
11695
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011696static int
11697xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11698 xmlSchemaTypePtr type)
11699{
11700 xmlSchemaTypePtr base, content;
11701 int OK = 0;
11702
11703 /*
11704 * TODO: Adjust the error codes here, as I used
11705 * XML_SCHEMAP_SRC_CT_1 only yet.
11706 */
11707 /*
11708 * Schema Representation Constraint:
11709 * Complex Type Definition Representation OK
11710 */
11711 base = type->baseType;
11712 if (base == NULL) {
11713 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11714 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11715 type->name);
11716 return (-1);
11717 }
11718
11719 if (type->subtypes != NULL) {
11720 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11721 if IS_COMPLEX_TYPE(base) {
11722 /*
11723 * 1 If the <complexContent> alternative is chosen, the type definition
11724 * ·resolved· to by the ·actual value· of the base [attribute]
11725 * must be a complex type definition;
11726 */
11727 xmlSchemaPCustomErr(ctxt,
11728 XML_SCHEMAP_SRC_CT_1,
11729 NULL, type, NULL,
11730 "The base type is not a complex type", NULL);
11731 return (XML_SCHEMAP_SRC_CT_1);
11732 }
11733 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11734
11735 if IS_SIMPLE_TYPE(base) {
11736 if (type->flags &
11737 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11738 /*
11739 * 2.1.3 only if the <extension> alternative is also
11740 * chosen, a simple type definition.
11741 */
11742 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11743 xmlSchemaPCustomErr(ctxt,
11744 XML_SCHEMAP_SRC_CT_1,
11745 NULL, type, NULL,
11746 "A complex type (simple content) cannot restrict "
11747 "an other simple type",
11748 NULL);
11749 return (XML_SCHEMAP_SRC_CT_1);
11750 }
11751 OK = 1;
11752
11753 } else { /* if IS_SIMPLE_TYPE(base) */
11754 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11755 /*
11756 * 2.1.2 only if the <restriction> alternative is also
11757 * chosen, a complex type definition whose {content type}
11758 * is mixed and a particle emptyable.
11759 */
11760 /*
11761 * FIXME TODO: Check for *empiable particle* is missing.
11762 */
11763 if ((type->flags &
11764 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11765 xmlSchemaPCustomErr(ctxt,
11766 XML_SCHEMAP_SRC_CT_1,
11767 NULL, type, NULL,
11768 "A complex type (simple content) cannot "
11769 "extend an other complex type which has a "
11770 "content type of: 'mixed' and emptiable particle",
11771 NULL);
11772 return (XML_SCHEMAP_SRC_CT_1);
11773 }
11774 /*
11775 * NOTE: This will be fired as well, if the base type
11776 * is *'anyType'*.
11777 * NOTE: type->subtypes->subtypes will be the
11778 * <restriction> item.
11779 */
11780 if (type->subtypes->subtypes == NULL) {
11781 /* Yes, this is paranoid programming. */
11782 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11783 NULL, type, NULL,
11784 "Internal error: xmlSchemaCheckSRCCT, "
11785 "'%s', <simpleContent> has no <restriction>",
11786 type->name);
11787 return (-1);
11788 }
11789 /*
11790 * 2.2 If clause 2.1.2 above is satisfied, then there
11791 * must be a <simpleType> among the [children] of
11792 * <restriction>.
11793 */
11794 if (type->subtypes->subtypes->type !=
11795 XML_SCHEMA_TYPE_SIMPLE) {
11796 /* TODO: Change error code to ..._SRC_CT_2_2. */
11797 xmlSchemaPCustomErr(ctxt,
11798 XML_SCHEMAP_SRC_CT_1,
11799 NULL, type, NULL,
11800 "A <simpleType> is expected among the children "
11801 "of <restriction>", NULL);
11802 return (XML_SCHEMAP_SRC_CT_1);
11803 }
11804 OK = 1;
11805 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
11806 /*
11807 * 2.1.1 a complex type definition whose {content type} is a
11808 * simple type definition;
11809 */
11810 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
11811 xmlSchemaPCustomErr(ctxt,
11812 XML_SCHEMAP_SRC_CT_1,
11813 NULL, type, NULL,
11814 "A complex type (simple content) cannot "
11815 "be derived from the complex type '%s'",
11816 base->name);
11817 return (XML_SCHEMAP_SRC_CT_1);
11818 }
11819 content = base->contentTypeDef;
11820 if (content == NULL) {
11821 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11822 NULL, type, NULL,
11823 "Internal error: xmlSchemaCheckSRCCT, "
11824 "'%s', base type has no content type",
11825 type->name);
11826 return (-1);
11827 }
11828 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
11829 xmlSchemaPCustomErr(ctxt,
11830 XML_SCHEMAP_SRC_CT_1,
11831 NULL, type, NULL,
11832 "A complex type (simple content) cannot "
11833 "be derived from the complex type '%s'",
11834 base->name);
11835 return (XML_SCHEMAP_SRC_CT_1);
11836 }
11837 }
11838 }
11839 }
11840 }
11841 /*
11842 * TODO: 3 The corresponding complex type definition component must
11843 * satisfy the conditions set out in Constraints on Complex Type
11844 * Definition Schema Components (§3.4.6);
11845 *
11846 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
11847 * above for {attribute wildcard} is satisfied, the intensional
11848 * intersection must be expressible, as defined in Attribute Wildcard
11849 * Intersection (§3.10.6).
11850 */
11851
11852}
William M. Brack2f2a6632004-08-20 23:09:47 +000011853#endif
11854
Daniel Veillard01fa6152004-06-29 17:04:39 +000011855/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011856 * xmlSchemaGroupDefFixup:
11857 * @typeDecl: the schema model group definition
11858 * @ctxt: the schema parser context
11859 *
11860 * Fixes model group definitions.
11861 */
11862static void
11863xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11864 xmlSchemaParserCtxtPtr ctxt,
11865 const xmlChar * name ATTRIBUTE_UNUSED)
11866{
11867 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11868 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11869 xmlSchemaTypePtr groupDef;
11870 /*
11871 * Resolve the reference.
11872 */
11873 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11874 group->refNs);
11875 if (groupDef == NULL) {
11876 xmlSchemaPResCompAttrErr(ctxt,
11877 XML_SCHEMAP_SRC_RESOLVE,
11878 NULL, group, NULL,
11879 "ref", group->ref, group->refNs,
11880 XML_SCHEMA_TYPE_GROUP, NULL);
11881 return;
11882 }
11883 group->subtypes = groupDef;
11884 }
11885}
11886
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011887#if 0 /* Enable when the content type will be computed. */
11888static int
11889xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
11890 xmlSchemaTypePtr type)
11891{
11892 xmlSchemaTypePtr base, res = NULL;
11893
11894 base = type->baseType;
11895 if (base == NULL) {
11896 xmlSchemaPCustomErr(ctxt,
11897 XML_SCHEMAP_INTERNAL,
11898 NULL, type, NULL,
11899 "Internal error: xmlSchemaGetContentType, "
11900 "the complex type '%s' has no base type", type->name);
11901 return (-1);
11902 }
11903 if (IS_ANYTYPE(base) || (type->subtypes->type ==
11904 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
11905 xmlSchemaTypePtr start;
11906 /*
11907 * Effective 'mixed'.
11908 */
11909 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
11910 type->contentType = XML_SCHEMA_CONTENT_MIXED;
11911 /*
11912 * Effective content.
11913 */
11914 if (IS_ANYTYPE(base))
11915 start = type;
11916 else
11917 start = type->subtypes;
11918
11919 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
11920 xmlSchemaTypePtr baseContentItem;
11921
11922 /*
11923 * Complex type with simple content.
11924 */
11925 if IS_COMPLEX_TYPE(base) {
11926 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11927 /*
11928 * Summary: a complex type (simple content) can *restrict*
11929 * a complex type with the following content type:
11930 * 1. 'mixed' and an emptiable particle
11931 * 2. simple type
11932 */
11933 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
11934 /*
11935 * 2 if the {content type} of the base type is mixed and a
11936 * particle which is ·emptiable·,
11937 * [...]
11938 * then starting from the simple type definition
11939 * corresponding to the <simpleType> among the [children]
11940 * of <restriction> (**which must be present**)
11941 *
11942 * FIXME TODO: Handle "emptiable particle".
11943 */
11944 res = type->subtypes->subtypes;
11945 if (res == NULL) {
11946 xmlSchemaPCustomErr(ctxt,
11947 XML_SCHEMAP_INTERNAL,
11948 NULL, type, NULL,
11949 "Internal error: xmlSchemaGetContentType, "
11950 "CT '%s' (restricting): <simpleContent> has no "
11951 "<restriction>",
11952 type->name);
11953 return (-1);
11954 }
11955
11956 res->subtypes;
11957 if (res == NULL) {
11958 xmlSchemaPCustomErr(ctxt,
11959 XML_SCHEMAP_INTERNAL,
11960 NULL, type, NULL,
11961 "Internal error: xmlSchemaGetContentType, "
11962 "CT '%s' (restricting): <restriction> has no "
11963 "mandatory <simpleType>",
11964 type->name);
11965 return (-1);
11966 }
11967 } else {
11968 baseContentItem = base->contentTypeDef;
11969 if (baseContentItem == NULL) {
11970 xmlSchemaPCustomErr(ctxt,
11971 XML_SCHEMAP_INTERNAL,
11972 NULL, type, NULL,
11973 "Internal error: xmlSchemaGetContentType, "
11974 "CT '%s' (restricting), the base type has no "
11975 "content type", type->name);
11976 return (-1);
11977 }
11978 if IS_SIMPLE_TYPE(baseContentItem) {
11979 /*
11980 * 1 If the base type is a complex type whose own
11981 * {content type} is a simple type and the <restriction>
11982 * alternative is chosen
11983 */
11984 /* type->subtypes->subtypes will be the restriction item.*/
11985 res = type->subtypes->subtypes;
11986 if (res == NULL) {
11987 xmlSchemaPCustomErr(ctxt,
11988 XML_SCHEMAP_INTERNAL,
11989 NULL, type, NULL,
11990 "Internal error: xmlSchemaGetContentType, "
11991 "CT '%s' (restricting): <simpleType> has no "
11992 "<restriction>", type->name);
11993 return (-1);
11994 }
11995 /*
11996 * 1.1 the simple type definition corresponding to the
11997 * <simpleType> among the [children] of <restriction>if
11998 * there is one;
11999 */
12000 res = res->subtypes;
12001 if (res == NULL) {
12002 /*
12003 * 1.2 otherwise the {content type}
12004 * of the base type .
12005 */
12006 res = baseContentItem;
12007 }
12008 }
12009 }
12010 /*
12011 * SPECIAL TODO: If *restricting* the spec wants us to
12012 * create an *additional* simple type which restricts the
12013 * located simple type; we won't do this yet, and look how
12014 * far we get with it.
12015 */
12016 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12017 /*
12018 * Summary: a complex type (simple content) can *extend*
12019 * only a complex base with a simple type as content.
12020 */
12021 /*
12022 * 3 If the type definition ·resolved· to by the ·actual
12023 * value· of the base [attribute] is a complex type
12024 * definition (whose own {content type} *must be* a simple
12025 * type definition, see below) and the *<extension>*
12026 * alternative is chosen, then the {content type} of that
12027 * complex type definition;
12028 */
12029 res = base->contentTypeDef;
12030 if (res == NULL) {
12031 xmlSchemaPCustomErr(ctxt,
12032 XML_SCHEMAP_INTERNAL,
12033 NULL, type, NULL,
12034 "Internal error: xmlSchemaGetContentType, "
12035 "CT '%s' (extending), the base type has no content "
12036 "type", type->name);
12037 return (-1);
12038 }
12039 if (! IS_SIMPLE_TYPE(res)) {
12040 xmlSchemaPCustomErr(ctxt,
12041 XML_SCHEMAP_INTERNAL,
12042 NULL, type, NULL,
12043 "Internal error: xmlSchemaGetContentType, "
12044 "CT '%s' (extending), the content type of the "
12045 "base is not a simple type", type->name);
12046 return (-1);
12047 }
12048 }
12049 } else /* if IS_COMPLEX_TYPE(base) */
12050 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12051 /*
12052 * 4 otherwise (the type definition ·resolved· to by the
12053 * ·actual value· of the base [attribute] is a simple type
12054 * definition and the <extension> alternative is chosen),
12055 * then that simple type definition.
12056 */
12057 res = base;
12058 }
12059 type->contentTypeDef = res;
12060 if (res == NULL) {
12061 xmlSchemaPCustomErr(ctxt,
12062 XML_SCHEMAP_INTERNAL,
12063 NULL, type, NULL,
12064 "Internal error: xmlSchemaGetContentType, "
12065 "'%s', the content type could not be determined",
12066 type->name);
12067 return (-1);
12068 }
12069
12070 }
12071
12072}
12073#endif
12074
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012075/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012076 * xmlSchemaTypeFixup:
12077 * @typeDecl: the schema type definition
12078 * @ctxt: the schema parser context
12079 *
12080 * Fixes the content model of the type.
12081 */
12082static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012083xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012084 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012085{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012086 xmlSchemaTypePtr ctxtType;
12087
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012088 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012089 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012090 /*
12091 * Do not allow the following types to be typefixed, prior to
12092 * the corresponding simple/complex types.
12093 */
12094 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012095 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012096 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12097 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12098 case XML_SCHEMA_TYPE_UNION:
12099 case XML_SCHEMA_TYPE_RESTRICTION:
12100 case XML_SCHEMA_TYPE_EXTENSION:
12101 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012102 default:
12103 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012104 }
12105 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012106 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012107 name = item->name;
12108 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12109 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012110 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012111 if (item->subtypes != NULL) {
12112 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012113 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012114 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012115 NULL);
12116 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012117 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012118 XML_SCHEMA_CONTENT_SIMPLE;
12119 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012120 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012121 break;
12122 }
12123 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012124 xmlSchemaTypePtr base = NULL;
12125
12126 ctxt->ctxtType->flags |=
12127 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012128 if (item->baseType != NULL)
12129 base = item->baseType;
12130 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012131 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012132 xmlSchemaGetType(ctxt->schema, item->base,
12133 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012134 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012135 xmlSchemaPResCompAttrErr(ctxt,
12136 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012137 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012138 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12139 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012140 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012141 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012142 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012143 xmlSchemaTypeFixup(base, ctxt, NULL);
12144 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012145 }
12146 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012147 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12148 /*
12149 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012150 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012151 /*
12152 * Content type.
12153 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012154 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012155 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012156 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12157 else if ((item->subtypes->subtypes == NULL) &&
12158 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012159 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012160 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012161 XML_SCHEMA_TYPE_SEQUENCE)))
12162 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012163 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12164 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012165 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012166 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012167 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012168 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012169 else {
12170 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012171 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012172 XML_SCHEMA_CONTENT_ELEMENTS;
12173 }
12174 } else {
12175 /*
12176 * SimpleType restriction.
12177 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012178 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012179 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012180 break;
12181 }
12182 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012183 xmlSchemaTypePtr base = NULL;
12184 xmlSchemaContentType explicitContentType;
12185
12186 /*
12187 * An extension does exist on a complexType only.
12188 */
12189 ctxt->ctxtType->flags |=
12190 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012191 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012192 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012193 xmlSchemaPCustomErr(ctxt,
12194 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012195 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012196 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012197 return;
12198 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012199 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012200 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012201 xmlSchemaGetType(ctxt->schema, item->base,
12202 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012203 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012204 xmlSchemaPResCompAttrErr(ctxt,
12205 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012206 NULL, item, item->node,
12207 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012208 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012209 } else if (base->contentType ==
12210 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012211 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012212 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012213 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012214 }
12215 /*
12216 * The type definition ·resolved· to by the ·actual
12217 * value· of the base [attribute]
12218 */
12219 ctxt->ctxtType->baseType = base;
12220 /*
12221 * TODO: This one is still needed for computation of
12222 * the content model by xmlSchemaBuildAContentModel.
12223 * Try to get rid of it.
12224 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012225 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012226 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012227 if ((item->subtypes != NULL) &&
12228 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12229 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012230
12231 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012232 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012233 /* 1.1.1 */
12234 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012235 else if ((item->subtypes->subtypes == NULL) &&
12236 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012237 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012238 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012239 XML_SCHEMA_TYPE_SEQUENCE)))
12240 /* 1.1.2 */
12241 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012242 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012243 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012244 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012245 /* 1.1.3 */
12246 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12247 if (base != NULL) {
12248 /* It will be reported later, if the base is missing. */
12249 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12250 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012251 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012252 } else if (base->contentType ==
12253 XML_SCHEMA_CONTENT_EMPTY) {
12254 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012255 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012256 XML_SCHEMA_CONTENT_ELEMENTS;
12257 } else {
12258 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012259 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012260 XML_SCHEMA_CONTENT_ELEMENTS;
12261 }
12262 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012263 break;
12264 }
12265 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012266 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012267 ctxt->ctxtType = item;
12268 /*
12269 * Start with an empty content-type type.
12270 */
12271 if (item->subtypes == NULL)
12272 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12273
12274 if ((item->subtypes == NULL) ||
12275 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012276 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012277 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012278 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12279 /*
12280 * This case is understood as shorthand for complex
12281 * content restricting the ur-type definition, and
12282 * the details of the mappings should be modified as
12283 * necessary.
12284 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012285 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12286 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012287 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012288 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012289 * Assume that we inherit the content-type type
12290 * from 'anyType', which is 'mixed' and a particle
12291 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012292 */
12293 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012294 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012295 /*
12296 * Fixup the sub components.
12297 */
12298 if ((item->subtypes != NULL) &&
12299 (item->subtypes->contentType ==
12300 XML_SCHEMA_CONTENT_UNKNOWN)) {
12301 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012302 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012303 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12304 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12305 } else if (item->subtypes != NULL) {
12306 /*
12307 * Use the content-type type of the model groups
12308 * defined, if 'mixed' is not set. If 'mixed' is set
12309 * it will expand the content-type by allowing character
12310 * content to appear.
12311 */
12312 item->contentType =
12313 item->subtypes->contentType;
12314 }
12315 xmlSchemaBuildAttributeValidation(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012316 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012317 break;
12318 }
12319 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012320 if (item->subtypes == NULL) {
12321 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12322 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12323 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012324 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012325 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012326 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12327 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012328 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012329 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012330 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012331 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012332 if (item->subtypes != NULL)
12333 item->contentType =
12334 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012335 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012336 /*
12337 * Removed due to implementation of the build of attribute uses.
12338 */
12339 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012340 if (item->attributes == NULL)
12341 item->attributes =
12342 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012343 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012344 }
12345 break;
12346 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012347 case XML_SCHEMA_TYPE_SIMPLE:
12348 /*
12349 * Simple Type Definition Schema Component
12350 *
12351 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012352 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012353 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12354 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012355 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012356 ctxt->ctxtType = item;
12357 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012358 }
12359 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012360 if ((item->baseType != NULL) &&
12361 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012362 XML_SCHEMA_CONTENT_UNKNOWN)) {
12363 /* OPTIMIZE: Actually this one will never by hit, since
12364 * the base type is already type-fixed in <restriction>.
12365 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012366 ctxt->ctxtType = item;
12367 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012368 }
12369 /* Base type:
12370 * 2 If the <list> or <union> alternative is chosen,
12371 * then the ·simple ur-type definition·.
12372 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012373 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012374 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012375 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12376 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12377 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012378 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012379 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12380 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12381 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012382 XML_SCHEMA_TYPE_RESTRICTION) {
12383 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12384
12385 /*
12386 * Variety
12387 * If the <restriction> alternative is chosen, then the
12388 * {variety} of the {base type definition}.
12389 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012390 if (item->baseType != NULL) {
12391 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012392 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012393 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12394 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012395 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012396 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12397 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012398 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012399 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012400 /*
12401 * Schema Component Constraint: Simple Type Restriction
12402 * (Facets)
12403 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12404 * applied beforehand.
12405 *
12406 * 3 The {facets} of R are the union of S and the {facets}
12407 * of B, eliminating duplicates. To eliminate duplicates,
12408 * when a facet of the same kind occurs in both S and the
12409 * {facets} of B, the one in the {facets} of B is not
12410 * included, with the exception of enumeration and pattern
12411 * facets, for which multiple occurrences with distinct values
12412 * are allowed.
12413 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012414 if (item->baseType->facetSet != NULL) {
12415 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012416 if (last != NULL)
12417 while (last->next != NULL)
12418 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012419 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012420 for (; cur != NULL; cur = cur->next) {
12421 /*
12422 * Base patterns won't be add here:
12423 * they are ORed in a type and
12424 * ANDed in derived types. This will
12425 * happed at validation level by
12426 * walking the base axis of the type.
12427 */
12428 if (cur->facet->type ==
12429 XML_SCHEMA_FACET_PATTERN)
12430 continue;
12431 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012432 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012433 (cur->facet->type !=
12434 XML_SCHEMA_FACET_PATTERN) &&
12435 (cur->facet->type !=
12436 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012437 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012438 do {
12439 if (cur->facet->type ==
12440 facet->facet->type)
12441 break;
12442 facet = facet->next;
12443 } while (facet != NULL);
12444 }
12445 if (facet == NULL) {
12446 facet = (xmlSchemaFacetLinkPtr)
12447 xmlMalloc(sizeof(xmlSchemaFacetLink));
12448 if (facet == NULL) {
12449 xmlSchemaPErrMemory(ctxt,
12450 "fixing simpleType", NULL);
12451 return;
12452 }
12453 facet->facet = cur->facet;
12454 facet->next = NULL;
12455 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012456 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012457 else
12458 last->next = facet;
12459 last = facet;
12460 }
12461 }
12462 }
12463 }
12464 }
12465 /*
12466 * Check constraints.
12467 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012468 xmlSchemaCheckSRCSimpleType(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012469 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012470 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012471 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012472 case XML_SCHEMA_TYPE_ALL:
12473 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012474 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012475 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012476 case XML_SCHEMA_TYPE_GROUP:
12477 /*
12478 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12479 */
12480 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012481 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012482 xmlSchemaParseListRefFixup(item, ctxt);
12483 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012484 break;
12485 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012486 xmlSchemaParseUnionRefCheck(item, ctxt);
12487 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012488 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012489 case XML_SCHEMA_TYPE_BASIC:
12490 case XML_SCHEMA_TYPE_ANY:
12491 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012492 case XML_SCHEMA_TYPE_UR:
12493 case XML_SCHEMA_TYPE_ELEMENT:
12494 case XML_SCHEMA_TYPE_ATTRIBUTE:
12495 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012496 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012497 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012498 case XML_SCHEMA_FACET_MININCLUSIVE:
12499 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12500 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12501 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12502 case XML_SCHEMA_FACET_TOTALDIGITS:
12503 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12504 case XML_SCHEMA_FACET_PATTERN:
12505 case XML_SCHEMA_FACET_ENUMERATION:
12506 case XML_SCHEMA_FACET_WHITESPACE:
12507 case XML_SCHEMA_FACET_LENGTH:
12508 case XML_SCHEMA_FACET_MAXLENGTH:
12509 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012510 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12511 if (item->subtypes != NULL)
12512 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012513 break;
12514 }
12515 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012516#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012517 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012518 xmlGenericError(xmlGenericErrorContext,
12519 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012520 item->node->doc->URL,
12521 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012522 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012523 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012524 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012525 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012526 case XML_SCHEMA_CONTENT_SIMPLE:
12527 xmlGenericError(xmlGenericErrorContext, "simple\n");
12528 break;
12529 case XML_SCHEMA_CONTENT_ELEMENTS:
12530 xmlGenericError(xmlGenericErrorContext, "elements\n");
12531 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012532 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012533 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12534 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012535 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012536 xmlGenericError(xmlGenericErrorContext, "empty\n");
12537 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012538 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012539 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12540 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012541 /* Removed, since not used. */
12542 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012543 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012544 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12545 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012546 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012547 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012548 xmlGenericError(xmlGenericErrorContext, "basic\n");
12549 break;
12550 default:
12551 xmlGenericError(xmlGenericErrorContext,
12552 "not registered !!!\n");
12553 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012554 }
12555#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012556}
12557
12558/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012559 * xmlSchemaCheckFacet:
12560 * @facet: the facet
12561 * @typeDecl: the schema type definition
12562 * @ctxt: the schema parser context or NULL
12563 * @name: name of the type
12564 *
12565 * Checks the default values types, especially for facets
12566 *
12567 * Returns 0 if okay or -1 in cae of error
12568 */
12569int
12570xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012571 xmlSchemaTypePtr typeDecl,
12572 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012573{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012574 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012575 int ret = 0, reuseValCtxt = 0;
12576
12577 /*
12578 * TODO: will the parser context be given if used from
12579 * the relaxNG module?
12580 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012581
12582 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012583 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012584 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012585 }
12586 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012587 case XML_SCHEMA_FACET_MININCLUSIVE:
12588 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12589 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012590 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12591 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012592 /*
12593 * Okay we need to validate the value
12594 * at that point.
12595 */
12596 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012597 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012598
12599 /* 4.3.5.5 Constraints on enumeration Schema Components
12600 * Schema Component Constraint: enumeration valid restriction
12601 * It is an ·error· if any member of {value} is not in the
12602 * ·value space· of {base type definition}.
12603 *
12604 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12605 * The value ·must· be in the
12606 * ·value space· of the ·base type·.
12607 */
12608 /*
12609 * This function is intended to deliver a compiled value
12610 * on the facet. In XML Schemas the type holding a facet,
12611 * cannot be a built-in type. Thus to ensure that other API
12612 * calls (relaxng) do work, if the given type is a built-in
12613 * type, we will assume that the given built-in type *is
12614 * already* the base type.
12615 */
12616 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12617 base = typeDecl->baseType;
12618 if (base == NULL) {
12619 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012620 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012621 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012622 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012623 typeDecl->name, NULL);
12624 return (-1);
12625 }
12626 } else
12627 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012628 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012629 * This avoids perseverative creation of the
12630 * validation context if a parser context is
12631 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012632 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012633 if (ctxt != NULL) {
12634 reuseValCtxt = 1;
12635 if (ctxt->vctxt == NULL) {
12636 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12637 return (-1);
12638 }
12639 vctxt = ctxt->vctxt;
12640 } else {
12641 vctxt = xmlSchemaNewValidCtxt(NULL);
12642 if (vctxt == NULL) {
12643 xmlSchemaPErr(ctxt, typeDecl->node,
12644 XML_SCHEMAP_INTERNAL,
12645 "Internal error: xmlSchemaCheckFacet, "
12646 "creating a new validation context.\n",
12647 NULL, NULL);
12648 return (-1);
12649 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012650 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012651
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012652 vctxt->node = facet->node;
12653 vctxt->cur = NULL;
12654 /*
12655 * NOTE: This call does not check the content nodes,
12656 * since they are not available:
12657 * facet->node is just the node holding the facet
12658 * definition, *not* the attribute holding the *value*
12659 * of the facet.
12660 */
12661 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12662 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012663 facet->val = vctxt->value;
12664 vctxt->value = NULL;
12665 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012666 /* error code */
12667 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012668 xmlSchemaPErrExt(ctxt, facet->node,
12669 XML_SCHEMAP_INVALID_FACET,
12670 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012671 "Type definition '%s': The value '%s' of the "
12672 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012673 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012674 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012675 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012676 }
12677 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012678 } else if (ret < 0) {
12679 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012680 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012681 NULL, NULL, NULL,
12682 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012683 "failed to validate the value '%s' name of the "
12684 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012685 facet->value,
12686 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12687 base->name, NULL, NULL);
12688 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012689 }
12690 if (reuseValCtxt == 0)
12691 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012692 break;
12693 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012694 case XML_SCHEMA_FACET_PATTERN:
12695 facet->regexp = xmlRegexpCompile(facet->value);
12696 if (facet->regexp == NULL) {
12697 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012698 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012699 "Type definition '%s': The value '%s' of the "
12700 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012701 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012702 ret = -1;
12703 }
12704 break;
12705 case XML_SCHEMA_FACET_TOTALDIGITS:
12706 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12707 case XML_SCHEMA_FACET_LENGTH:
12708 case XML_SCHEMA_FACET_MAXLENGTH:
12709 case XML_SCHEMA_FACET_MINLENGTH:{
12710 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012711
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012712 tmp =
12713 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12714 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012715 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012716 if (tmp != 0) {
12717 /* error code */
12718 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012719 xmlSchemaPErrExt(ctxt, facet->node,
12720 XML_SCHEMAP_INVALID_FACET_VALUE,
12721 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012722 "Type definition '%s': The value '%s' of the "
12723 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012724 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012725 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012726 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012727 }
12728 ret = -1;
12729 }
12730 break;
12731 }
12732 case XML_SCHEMA_FACET_WHITESPACE:{
12733 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12734 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12735 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12736 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12737 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12738 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12739 } else {
12740 if (ctxt != NULL) {
12741 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012742 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012743 "Type definition '%s': The value '%s' of the "
12744 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012745 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012746 }
12747 ret = -1;
12748 }
12749 }
12750 default:
12751 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012752 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012753 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012754}
12755
12756/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012757 * xmlSchemaCheckDefaults:
12758 * @typeDecl: the schema type definition
12759 * @ctxt: the schema parser context
12760 *
12761 * Checks the default values types, especially for facets
12762 */
12763static void
12764xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012765 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012766{
Daniel Veillard4255d502002-04-16 15:50:10 +000012767 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012768 name = typeDecl->name;
12769 /*
12770 * NOTE: It is intended to use the facets list, instead
12771 * of facetSet.
12772 */
12773 if (typeDecl->facets != NULL) {
12774 xmlSchemaFacetPtr facet = typeDecl->facets;
12775
12776 while (facet != NULL) {
12777 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12778 facet = facet->next;
12779 }
12780 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012781}
12782
12783/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012784 * xmlSchemaGetCircModelGrDefRef:
12785 * @ctxtGr: the searched model group
12786 * @list: the list of model groups to be processed
12787 *
12788 * This one is intended to be used by
12789 * xmlSchemaCheckGroupDefCircular only.
12790 *
12791 * Returns the circular model group definition reference, otherwise NULL.
12792 */
12793static xmlSchemaTypePtr
12794xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12795 xmlSchemaTypePtr gr)
12796{
12797 xmlSchemaTypePtr circ = NULL;
12798 int marked;
12799 /*
12800 * We will search for an model group reference which
12801 * references the context model group definition.
12802 */
12803 while (gr != NULL) {
12804 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
12805 (gr->type == XML_SCHEMA_TYPE_ALL) ||
12806 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
12807 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
12808 (gr->subtypes != NULL)) {
12809 marked = 0;
12810 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
12811 (gr->ref != NULL)) {
12812 if (gr->subtypes == ctxtGrDef)
12813 return (gr);
12814 else if (gr->subtypes->flags &
12815 XML_SCHEMAS_TYPE_MARKED) {
12816 gr = gr->next;
12817 continue;
12818 } else {
12819 /*
12820 * Mark to avoid infinite recursion on
12821 * circular references not yet examined.
12822 */
12823 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
12824 marked = 1;
12825 }
12826 if (gr->subtypes->subtypes != NULL)
12827 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12828 gr->subtypes->subtypes);
12829 /*
12830 * Unmark the visited model group definition.
12831 */
12832 if (marked)
12833 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
12834 if (circ != NULL)
12835 return (circ);
12836 } else {
12837 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12838 (xmlSchemaTypePtr) gr->subtypes);
12839 if (circ != NULL)
12840 return (circ);
12841 }
12842
12843 }
12844 gr = gr->next;
12845 }
12846 return (NULL);
12847}
12848
12849/**
12850 * xmlSchemaCheckGroupDefCircular:
12851 * attrGr: the model group definition
12852 * @ctxt: the parser context
12853 * @name: the name
12854 *
12855 * Checks for circular references to model group definitions.
12856 */
12857static void
12858xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
12859 xmlSchemaParserCtxtPtr ctxt,
12860 const xmlChar * name ATTRIBUTE_UNUSED)
12861{
12862 /*
12863 * Schema Component Constraint: Model Group Correct
12864 * 2 Circular groups are disallowed. That is, within the {particles}
12865 * of a group there must not be at any depth a particle whose {term}
12866 * is the group itself.
12867 */
12868 /*
12869 * NOTE: "gr->subtypes" holds the referenced group.
12870 */
12871 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
12872 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
12873 (modelGrDef->subtypes == NULL))
12874 return;
12875 else {
12876 xmlSchemaTypePtr circ;
12877
12878 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
12879 if (circ != NULL) {
12880 /*
12881 * TODO: Report the referenced attr group as QName.
12882 */
12883 xmlSchemaPCustomErr(ctxt,
12884 XML_SCHEMAP_MG_PROPS_CORRECT_2,
12885 NULL, NULL, circ->node,
12886 "Circular reference to the model group definition '%s' "
12887 "defined", modelGrDef->name);
12888 /*
12889 * NOTE: We will cut the reference to avoid further
12890 * confusion of the processor.
12891 * TODO: SPEC: Does the spec define how to process here?
12892 */
12893 circ->subtypes = NULL;
12894 }
12895 }
12896}
12897
12898
12899/**
12900 * xmlSchemaGetCircAttrGrRef:
12901 * @ctxtGr: the searched attribute group
12902 * @attr: the current attribute list to be processed
12903 *
12904 * This one is intended to be used by
12905 * xmlSchemaCheckSRCAttributeGroupCircular only.
12906 *
12907 * Returns the circular attribute grou reference, otherwise NULL.
12908 */
12909static xmlSchemaAttributeGroupPtr
12910xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
12911 xmlSchemaAttributePtr attr)
12912{
12913 xmlSchemaAttributeGroupPtr circ = NULL, gr;
12914 int marked;
12915 /*
12916 * We will search for an attribute group reference which
12917 * references the context attribute group.
12918 */
12919 while (attr != NULL) {
12920 marked = 0;
12921 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12922 gr = (xmlSchemaAttributeGroupPtr) attr;
12923 if (gr->refItem != NULL) {
12924 if (gr->refItem == ctxtGr)
12925 return (gr);
12926 else if (gr->refItem->flags &
12927 XML_SCHEMAS_ATTRGROUP_MARKED) {
12928 attr = attr->next;
12929 continue;
12930 } else {
12931 /*
12932 * Mark as visited to avoid infinite recursion on
12933 * circular references not yet examined.
12934 */
12935 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
12936 marked = 1;
12937 }
12938 }
12939 if (gr->attributes != NULL)
12940 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
12941 /*
12942 * Unmark the visited group's attributes.
12943 */
12944 if (marked)
12945 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
12946 if (circ != NULL)
12947 return (circ);
12948 }
12949 attr = attr->next;
12950 }
12951 return (NULL);
12952}
12953
12954/**
12955 * xmlSchemaCheckSRCAttributeGroupCircular:
12956 * attrGr: the attribute group definition
12957 * @ctxt: the parser context
12958 * @name: the name
12959 *
12960 * Checks for circular references of attribute groups.
12961 */
12962static void
12963xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
12964 xmlSchemaParserCtxtPtr ctxt,
12965 const xmlChar * name ATTRIBUTE_UNUSED)
12966{
12967 /*
12968 * Schema Representation Constraint:
12969 * Attribute Group Definition Representation OK
12970 * 3 Circular group reference is disallowed outside <redefine>.
12971 * That is, unless this element information item's parent is
12972 * <redefine>, then among the [children], if any, there must
12973 * not be an <attributeGroup> with ref [attribute] which resolves
12974 * to the component corresponding to this <attributeGroup>. Indirect
12975 * circularity is also ruled out. That is, when QName resolution
12976 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
12977 * any <attributeGroup>s with a ref [attribute] among the [children],
12978 * it must not be the case that a ·QName· is encountered at any depth
12979 * which resolves to the component corresponding to this <attributeGroup>.
12980 */
12981 /*
12982 * Only global components can be referenced.
12983 */
12984 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
12985 (attrGr->attributes == NULL))
12986 return;
12987 else {
12988 xmlSchemaAttributeGroupPtr circ;
12989
12990 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
12991 if (circ != NULL) {
12992 /*
12993 * TODO: Report the referenced attr group as QName.
12994 */
12995 xmlSchemaPCustomErr(ctxt,
12996 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
12997 NULL, NULL, circ->node,
12998 "Circular reference to the attribute group '%s' "
12999 "defined", attrGr->name);
13000 /*
13001 * NOTE: We will cut the reference to avoid further
13002 * confusion of the processor.
13003 * BADSPEC: The spec should define how to process in this case.
13004 */
13005 circ->attributes = NULL;
13006 circ->refItem = NULL;
13007 }
13008 }
13009}
13010
13011/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013012 * xmlSchemaAttrGrpFixup:
13013 * @attrgrpDecl: the schema attribute definition
13014 * @ctxt: the schema parser context
13015 * @name: the attribute name
13016 *
13017 * Fixes finish doing the computations on the attributes definitions
13018 */
13019static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013020xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013021 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013022{
13023 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013024 name = attrgrp->name;
13025 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013026 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013027 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013028 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013029
Daniel Veillardc0826a72004-08-10 14:17:33 +000013030 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13031 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013032 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013033 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013034 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013035 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13036 "ref", attrgrp->ref, attrgrp->refNs,
13037 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013038 return;
13039 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013040 attrgrp->refItem = ref;
13041 /*
13042 * Check for self reference!
13043 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013044 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013045 attrgrp->attributes = ref->attributes;
13046 attrgrp->attributeWildcard = ref->attributeWildcard;
13047 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013048}
13049
13050/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013051 * xmlSchemaAttrCheckValConstr:
13052 * @item: an schema attribute declaration/use
13053 * @ctxt: a schema parser context
13054 * @name: the name of the attribute
13055 *
13056 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013057 *
13058 * Fixes finish doing the computations on the attributes definitions
13059 */
13060static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013061xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13062 xmlSchemaParserCtxtPtr ctxt,
13063 const xmlChar * name ATTRIBUTE_UNUSED)
13064{
13065
13066 /*
13067 * a-props-correct
13068 * Schema Component Constraint: Attribute Declaration Properties Correct
13069 *
13070 * 2 if there is a {value constraint}, the canonical lexical
13071 * representation of its value must be ·valid· with respect
13072 * to the {type definition} as defined in String Valid (§3.14.4).
13073 */
13074
13075 if (item->defValue != NULL) {
13076 int ret;
13077 xmlNodePtr node;
13078 xmlSchemaTypePtr type;
13079
13080 if (item->subtypes == NULL) {
13081 xmlSchemaPErr(ctxt, item->node,
13082 XML_SCHEMAP_INTERNAL,
13083 "Internal error: xmlSchemaCheckAttrValConstr, "
13084 "type is missing... skipping validation of "
13085 "value constraint", NULL, NULL);
13086 return;
13087 }
13088
13089 /*
13090 * TODO: Try to avoid creating a new context.
13091 * TODO: This all is not very performant.
13092 */
13093 type = item->subtypes;
13094 /*
13095 * Ensure there's validation context.
13096 */
13097 if (ctxt->vctxt == NULL) {
13098 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13099 xmlSchemaPErr(ctxt, item->node,
13100 XML_SCHEMAP_INTERNAL,
13101 "Internal error: xmlSchemaCheckAttrValConstr, "
13102 "creating a new validation context.\n",
13103 NULL, NULL);
13104 return;
13105 }
13106 }
13107
13108 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13109 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13110 else
13111 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13112 ctxt->vctxt->node = node;
13113 ctxt->vctxt->cur = NULL;
13114 /*
13115 * NOTE: This call does not check the content nodes,
13116 * since they are not available:
13117 * facet->node is just the node holding the facet
13118 * definition, *not* the attribute holding the *value*
13119 * of the facet.
13120 */
13121 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13122 item->defValue, 0, 1, 1, 0);
13123 if (ret == 0) {
13124 /*
13125 * Store the computed value.
13126 */
13127 item->defVal = ctxt->vctxt->value;
13128 ctxt->vctxt->value = NULL;
13129 } else if (ret > 0) {
13130 if (ctxt != NULL) {
13131 xmlSchemaPSimpleTypeErr(ctxt,
13132 XML_SCHEMAP_A_PROPS_CORRECT_2,
13133 NULL, NULL, node,
13134 type, NULL, item->defValue,
13135 NULL, NULL, NULL);
13136 }
13137 } else if (ret < 0) {
13138 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13139 NULL, NULL, node,
13140 "Internal error: xmlSchemaAttrCheckValConstr, "
13141 "failed to validate the value constraint of the "
13142 "attribute decl/use against the type '%s'",
13143 type->name);
13144 }
13145 }
13146}
13147
13148#if 0 /* Not used yet. */
13149static int
13150xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13151 xmlSchemaElementPtr edecl)
13152{
13153 /*
13154 * TODO: 1 The values of the properties of an element declaration must be as
13155 * described in the property tableau in The Element Declaration Schema
13156 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13157 */
13158 /*
13159 * 2 If there is a {value constraint}, the canonical lexical
13160 * representation of its value must be ·valid· with respect to the {type
13161 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13162 *
13163 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13164 */
13165 /*
13166 * 3 If there is a non-·absent· {substitution group affiliation},
13167 * then {scope} must be global.
13168 *
13169 * NOTE: This is done in xmlSchemaParseElement.
13170 * TODO: Move it to this layer here.
13171 */
13172 /*
13173 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13174 * of the element declaration must be validly derived from the {type
13175 * definition} of the {substitution group affiliation}, given the value
13176 * of the {substitution group exclusions} of the {substitution group
13177 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13178 * (if the {type definition} is complex) or as defined in
13179 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13180 * simple).
13181 */
13182 /*
13183 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13184 * is or is derived from ID then there must not be a {value constraint}.
13185 * Note: The use of ID as a type definition for elements goes beyond
13186 * XML 1.0, and should be avoided if backwards compatibility is desired
13187 */
13188 /*
13189 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13190 * be possible to return to an element declaration by repeatedly following
13191 * the {substitution group affiliation} property.
13192 */
13193}
13194#endif
13195
13196/**
13197 * xmlSchemaCheckElemValConstr:
13198 * @item: an schema element declaration/particle
13199 * @ctxt: a schema parser context
13200 * @name: the name of the attribute
13201 *
13202 * Validates the value constraints of an element declaration.
13203 *
13204 * Fixes finish doing the computations on the element declarations.
13205 */
13206static void
13207xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13208 xmlSchemaParserCtxtPtr ctxt,
13209 const xmlChar * name ATTRIBUTE_UNUSED)
13210{
13211 if (decl->value != NULL) {
13212 int ret;
13213 xmlNodePtr node = NULL;
13214 xmlSchemaTypePtr type;
13215
13216 /*
13217 * 2 If there is a {value constraint}, the canonical lexical
13218 * representation of its value must be ·valid· with respect to the {type
13219 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13220 */
13221 if (decl->subtypes == NULL) {
13222 xmlSchemaPErr(ctxt, decl->node,
13223 XML_SCHEMAP_INTERNAL,
13224 "Internal error: xmlSchemaCheckElemValConstr, "
13225 "type is missing... skipping validation of "
13226 "the value constraint", NULL, NULL);
13227 return;
13228 }
13229 /*
13230 * Ensure there's a validation context.
13231 */
13232 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13233 return;
13234
13235 type = decl->subtypes;
13236
13237 if (decl->node != NULL) {
13238 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13239 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13240 else
13241 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13242 }
13243 ctxt->vctxt->node = node;
13244 ctxt->vctxt->cur = NULL;
13245 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13246 node);
13247 if (ret == 0) {
13248 /*
13249 * Consume the computed value.
13250 */
13251 decl->defVal = ctxt->vctxt->value;
13252 ctxt->vctxt->value = NULL;
13253 } else if (ret < 0) {
13254 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13255 NULL, NULL, node,
13256 "Internal error: xmlSchemaElemCheckValConstr, "
13257 "failed to validate the value constraint of the "
13258 "element declaration '%s'",
13259 decl->name);
13260 }
13261 }
13262}
13263
13264/**
13265 * xmlSchemaAttrFixup:
13266 * @item: an schema attribute declaration/use.
13267 * @ctxt: a schema parser context
13268 * @name: the name of the attribute
13269 *
13270 * Fixes finish doing the computations on attribute declarations/uses.
13271 */
13272static void
13273xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13274 xmlSchemaParserCtxtPtr ctxt,
13275 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013276{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013277 /*
13278 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013279 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013280 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013281 /*
13282 * The simple type definition corresponding to the <simpleType> element
13283 * information item in the [children], if present, otherwise the simple
13284 * type definition ·resolved· to by the ·actual value· of the type
13285 * [attribute], if present, otherwise the ·simple ur-type definition·.
13286 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013287 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013288 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013289 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13290 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013291 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013292 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013293 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013294
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013295 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13296 item->typeNs);
13297 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013298 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013299 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013300 NULL, (xmlSchemaTypePtr) item, item->node,
13301 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013302 XML_SCHEMA_TYPE_SIMPLE, NULL);
13303 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013304 item->subtypes = type;
13305
13306 } else if (item->ref != NULL) {
13307 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013308
Daniel Veillardc0826a72004-08-10 14:17:33 +000013309 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013310 * We have an attribute use here; assign the referenced
13311 * attribute declaration.
13312 */
13313 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013314 * TODO: Evaluate, what errors could occur if the declaration is not
13315 * found. It might be possible that the "typefixup" might crash if
13316 * no ref declaration was found.
13317 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013318 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13319 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013320 xmlSchemaPResCompAttrErr(ctxt,
13321 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013322 NULL, (xmlSchemaTypePtr) item, item->node,
13323 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013324 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013325 return;
13326 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013327 item->refDecl = decl;
13328 xmlSchemaAttrFixup(decl, ctxt, NULL);
13329
13330 item->subtypes = decl->subtypes;
13331 /*
13332 * Attribute Use Correct
13333 * au-props-correct.2: If the {attribute declaration} has a fixed
13334 * {value constraint}, then if the attribute use itself has a
13335 * {value constraint}, it must also be fixed and its value must match
13336 * that of the {attribute declaration}'s {value constraint}.
13337 */
13338 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13339 (item->defValue != NULL)) {
13340 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13341 (!xmlStrEqual(item->defValue, decl->defValue))) {
13342 xmlSchemaPCustomErr(ctxt,
13343 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13344 NULL, NULL, item->node,
13345 "The value constraint must be fixed "
13346 "and match the referenced attribute "
13347 "declarations's value constraint '%s'",
13348 decl->defValue);
13349 }
13350 /*
13351 * FUTURE: One should change the values of the attr. use
13352 * if ever validation should be attempted even if the
13353 * schema itself was not fully valid.
13354 */
13355 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013356 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013357 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13358 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013359}
13360
13361/**
13362 * xmlSchemaParse:
13363 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013364 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013365 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013366 * XML Shema struture which can be used to validate instances.
13367 * *WARNING* this interface is highly subject to change
13368 *
13369 * Returns the internal XML Schema structure built from the resource or
13370 * NULL in case of error
13371 */
13372xmlSchemaPtr
13373xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13374{
13375 xmlSchemaPtr ret = NULL;
13376 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013377 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013378 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013379
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013380 /*
13381 * This one is used if the schema to be parsed was specified via
13382 * the API; i.e. not automatically by the validated instance document.
13383 */
13384
Daniel Veillard4255d502002-04-16 15:50:10 +000013385 xmlSchemaInitTypes();
13386
Daniel Veillard6045c902002-10-09 21:13:59 +000013387 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013388 return (NULL);
13389
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013390 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013391 ctxt->counter = 0;
13392 ctxt->container = NULL;
13393
13394 /*
13395 * First step is to parse the input document into an DOM/Infoset
13396 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013397 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013398 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13399 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013400 if (doc == NULL) {
13401 xmlSchemaPErr(ctxt, NULL,
13402 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013403 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013404 ctxt->URL, NULL);
13405 return (NULL);
13406 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013407 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013408 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13409 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013410 if (doc == NULL) {
13411 xmlSchemaPErr(ctxt, NULL,
13412 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013413 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013414 NULL, NULL);
13415 return (NULL);
13416 }
13417 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013418 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013419 } else if (ctxt->doc != NULL) {
13420 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013421 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013422 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013423 xmlSchemaPErr(ctxt, NULL,
13424 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013425 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013426 NULL, NULL);
13427 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013428 }
13429
13430 /*
13431 * Then extract the root and Schema parse it
13432 */
13433 root = xmlDocGetRootElement(doc);
13434 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013435 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13436 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013437 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013438 if (!preserve) {
13439 xmlFreeDoc(doc);
13440 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013441 return (NULL);
13442 }
13443
13444 /*
13445 * Remove all the blank text nodes
13446 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013447 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013448
13449 /*
13450 * Then do the parsing for good
13451 */
13452 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013453 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013454 if (!preserve) {
13455 xmlFreeDoc(doc);
13456 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013457 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013458 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013459 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013460 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013461 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013462 ctxt->ctxtType = NULL;
13463 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013464 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013465 * Then fixup all attributes declarations
13466 */
13467 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13468
13469 /*
13470 * Then fixup all attributes group declarations
13471 */
13472 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13473 ctxt);
13474
13475 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013476 * Check attribute groups for circular references.
13477 */
13478 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13479 xmlSchemaCheckAttributeGroupCircular, ctxt);
13480
13481 /*
13482 * Then fixup all model group definitions.
13483 */
13484 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013485
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013486 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013487 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013488 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013489 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013490
13491 /*
13492 * Then fix references of element declaration; apply constraints.
13493 */
13494 xmlHashScanFull(ret->elemDecl,
13495 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013496
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013497 /*
13498 * Check model groups defnitions for circular references.
13499 */
13500 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13501 xmlSchemaCheckGroupDefCircular, ctxt);
13502
Daniel Veillard4255d502002-04-16 15:50:10 +000013503 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013504 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013505 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013506 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013507 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013508
13509 /*
13510 * Then check the defaults part of the type like facets values
13511 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013512 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
13513 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013514
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013515 /*
13516 * Validate the value constraint of attribute declarations/uses.
13517 */
13518 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13519
13520 /*
13521 * Validate the value constraint of element declarations.
13522 */
13523 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13524
Daniel Veillardc0826a72004-08-10 14:17:33 +000013525
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013526 if (ctxt->nberrors != 0) {
13527 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013528 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013529 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013530 return (ret);
13531}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013532
Daniel Veillard4255d502002-04-16 15:50:10 +000013533/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013534 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013535 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013536 * @err: the error callback
13537 * @warn: the warning callback
13538 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013539 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013540 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013541 */
13542void
13543xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013544 xmlSchemaValidityErrorFunc err,
13545 xmlSchemaValidityWarningFunc warn, void *ctx)
13546{
Daniel Veillard4255d502002-04-16 15:50:10 +000013547 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013548 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013549 ctxt->error = err;
13550 ctxt->warning = warn;
13551 ctxt->userData = ctx;
13552}
13553
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013554/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013555 * xmlSchemaGetParserErrors:
13556 * @ctxt: a XMl-Schema parser context
13557 * @err: the error callback result
13558 * @warn: the warning callback result
13559 * @ctx: contextual data for the callbacks result
13560 *
13561 * Get the callback information used to handle errors for a parser context
13562 *
13563 * Returns -1 in case of failure, 0 otherwise
13564 */
13565int
13566xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13567 xmlSchemaValidityErrorFunc * err,
13568 xmlSchemaValidityWarningFunc * warn, void **ctx)
13569{
13570 if (ctxt == NULL)
13571 return(-1);
13572 if (err != NULL)
13573 *err = ctxt->error;
13574 if (warn != NULL)
13575 *warn = ctxt->warning;
13576 if (ctx != NULL)
13577 *ctx = ctxt->userData;
13578 return(0);
13579}
13580
13581/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013582 * xmlSchemaFacetTypeToString:
13583 * @type: the facet type
13584 *
13585 * Convert the xmlSchemaTypeType to a char string.
13586 *
13587 * Returns the char string representation of the facet type if the
13588 * type is a facet and an "Internal Error" string otherwise.
13589 */
13590static const char *
13591xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13592{
13593 switch (type) {
13594 case XML_SCHEMA_FACET_PATTERN:
13595 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013596 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013597 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013598 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013599 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013600 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013601 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013602 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013603 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013604 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013605 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013606 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013607 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013608 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013609 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013610 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013611 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013612 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013613 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013614 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013615 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013616 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013617 return ("fractionDigits");
13618 default:
13619 break;
13620 }
13621 return ("Internal Error");
13622}
13623
Daniel Veillardc0826a72004-08-10 14:17:33 +000013624static xmlChar *
13625xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
13626 const xmlChar *cur = value;
13627 xmlChar *ret = NULL, *mcur;
13628
13629 if (value == NULL)
13630 return(NULL);
13631
13632 while ((*cur != 0) &&
13633 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
13634 cur++;
13635 }
13636 if (*cur == 0)
13637 return (NULL);
13638 ret = xmlStrdup(value);
13639 /* TODO FIXME: I guess gcc will bark at this. */
13640 mcur = (xmlChar *) (ret + (cur - value));
13641 do {
13642 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
13643 *mcur = ' ';
13644 mcur++;
13645 } while (*mcur != 0);
13646 return(ret);
13647}
13648
13649static int
13650xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13651{
13652 xmlSchemaTypePtr anc;
13653
13654 /*
13655 * The normalization type can be changed only for types which are derived
13656 * from xsd:string.
13657 */
13658 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13659 if ((type->builtInType == XML_SCHEMAS_STRING) &&
13660 (type->builtInType == XML_SCHEMAS_NORMSTRING))
13661
13662 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13663 else {
13664 /*
13665 * For all ·atomic· datatypes other than string (and types ·derived·
13666 * by ·restriction· from it) the value of whiteSpace is fixed to
13667 * collapse
13668 */
13669 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13670 }
13671 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13672 /*
13673 * For list types the facet "whiteSpace" is fixed to "collapse".
13674 */
13675 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13676 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13677 return (-1);
13678 } else if (type->facetSet != NULL) {
13679 xmlSchemaTypePtr anyST;
13680 xmlSchemaFacetLinkPtr lin;
13681
13682 /*
13683 * Atomic types.
13684 */
13685 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13686 anc = type->baseType;
13687 do {
13688 /*
13689 * For all ·atomic· datatypes other than string (and types ·derived·
13690 * by ·restriction· from it) the value of whiteSpace is fixed to
13691 * collapse
13692 */
13693 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13694 (anc->builtInType == XML_SCHEMAS_STRING)) {
13695
13696 lin = type->facetSet;
13697 do {
13698 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13699 if (lin->facet->whitespace ==
13700 XML_SCHEMAS_FACET_COLLAPSE) {
13701 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13702 } else if (lin->facet->whitespace ==
13703 XML_SCHEMAS_FACET_REPLACE) {
13704 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13705 } else
13706 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13707 break;
13708 }
13709 lin = lin->next;
13710 } while (lin != NULL);
13711 break;
13712 }
13713 anc = anc->baseType;
13714 } while (anc != anyST);
13715 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13716 }
13717 return (-1);
13718}
13719
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013720/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013721 * xmlSchemaValidateFacetsInternal:
13722 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013723 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013724 * @facets: the list of facets to check
13725 * @value: the lexical repr of the value to validate
13726 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013727 * @fireErrors: if 0, only internal errors will be fired;
13728 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013729 *
13730 * Check a value against all facet conditions
13731 *
13732 * Returns 0 if the element is schemas valid, a positive error code
13733 * number otherwise and -1 in case of internal or API error.
13734 */
13735static int
13736xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013737 xmlSchemaTypePtr type,
13738 const xmlChar * value,
13739 unsigned long length,
13740 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013741{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013742 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013743 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013744 xmlSchemaTypePtr biType; /* The build-in type. */
13745 xmlSchemaTypePtr tmpType;
13746 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013747 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013748 xmlSchemaFacetPtr facet;
13749 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013750
Daniel Veillardc0826a72004-08-10 14:17:33 +000013751#ifdef DEBUG_UNION_VALIDATION
13752 printf("Facets of type: '%s'\n", (const char *) type->name);
13753 printf(" fireErrors: %d\n", fireErrors);
13754#endif
13755
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013756 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013757 /*
13758 * NOTE: Do not jump away, if the facetSet of the given type is
13759 * empty: until now, "pattern" facets of the *base types* need to
13760 * be checked as well.
13761 */
13762 biType = type->baseType;
13763 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13764 biType = biType->baseType;
13765 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013766 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013767 "Internal error: xmlSchemaValidateFacetsInternal, "
13768 "the base type axis of the given type '%s' does not resolve to "
13769 "a built-in type.\n",
13770 type->name, NULL);
13771 return (-1);
13772 }
13773
13774 if (type->facetSet != NULL) {
13775 facetLink = type->facetSet;
13776 while (facetLink != NULL) {
13777 facet = facetLink->facet;
13778 /*
13779 * Skip the pattern "whiteSpace": it is used to
13780 * format the character content beforehand.
13781 */
13782 switch (facet->type) {
13783 case XML_SCHEMA_FACET_WHITESPACE:
13784 case XML_SCHEMA_FACET_PATTERN:
13785 case XML_SCHEMA_FACET_ENUMERATION:
13786 break;
13787 case XML_SCHEMA_FACET_LENGTH:
13788 case XML_SCHEMA_FACET_MINLENGTH:
13789 case XML_SCHEMA_FACET_MAXLENGTH:
13790 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13791 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13792 value, length, 0);
13793 len = length;
13794 } else
13795 ret = xmlSchemaValidateLengthFacet(biType, facet,
13796 value, ctxt->value, &len);
13797 break;
13798 default:
13799 ret = xmlSchemaValidateFacet(biType, facet, value,
13800 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013802 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013803 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013804 "Internal error: xmlSchemaValidateFacetsInternal, "
13805 "validating facet of type '%s'.\n",
13806 type->name, NULL);
13807 break;
13808 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013809 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013810 type, facet, NULL, NULL, NULL, NULL);
13811 }
13812
13813 facetLink = facetLink->next;
13814 }
13815 if (ret >= 0) {
13816 /*
13817 * Process enumerations.
13818 */
13819 retFacet = 0;
13820 facetLink = type->facetSet;
13821 while (facetLink != NULL) {
13822 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
13823 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13824 value, ctxt->value);
13825 if (retFacet <= 0)
13826 break;
13827 }
13828 facetLink = facetLink->next;
13829 }
13830 if (retFacet > 0) {
13831 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
13832 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013833 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013834 value, 0, type, NULL, NULL, NULL, NULL, NULL);
13835 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013836 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013837 "Internal error: xmlSchemaValidateFacetsInternal, "
13838 "validating facet of type '%s'.\n",
13839 BAD_CAST "enumeration", NULL);
13840 ret = -1;
13841 }
13842 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013843 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013844 if (ret >= 0) {
13845 /*
13846 * Process patters. Pattern facets are ORed at type level
13847 * and ANDed if derived. Walk the base type axis.
13848 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013849 tmpType = type;
13850 facet = NULL;
13851 do {
13852 retFacet = 0;
13853 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013854 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013855 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13856 continue;
13857 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13858 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013859 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013860 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013861 else if (retFacet < 0) {
13862 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13863 "Internal error: xmlSchemaValidateFacetsInternal, "
13864 "validating 'pattern' facet '%s' of type '%s'.\n",
13865 facetLink->facet->value, tmpType->name);
13866 ret = -1;
13867 break;
13868 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013869 /* Save the last non-validating facet. */
13870 facet = facetLink->facet;
13871 }
13872 if (retFacet != 0)
13873 break;
13874 tmpType = tmpType->baseType;
13875 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013876 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013877 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13878 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013879 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013880 NULL, NULL, NULL, NULL);
13881 }
13882 }
13883 }
13884
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013885 return (ret);
13886}
13887
Daniel Veillard4255d502002-04-16 15:50:10 +000013888/************************************************************************
13889 * *
13890 * Simple type validation *
13891 * *
13892 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013893
Daniel Veillard4255d502002-04-16 15:50:10 +000013894
13895/************************************************************************
13896 * *
13897 * DOM Validation code *
13898 * *
13899 ************************************************************************/
13900
Daniel Veillard4255d502002-04-16 15:50:10 +000013901static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013902 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013903 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013904static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013905 xmlSchemaTypePtr type,
13906 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000013907
Daniel Veillard3646d642004-06-02 19:19:14 +000013908
13909/**
13910 * xmlSchemaFreeAttrStates:
13911 * @state: a list of attribute states
13912 *
13913 * Free the given list of attribute states
13914 *
13915 */
13916static void
13917xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13918{
13919 xmlSchemaAttrStatePtr tmp;
13920 while (state != NULL) {
13921 tmp = state;
13922 state = state->next;
13923 xmlFree(tmp);
13924 }
13925}
13926
Daniel Veillard4255d502002-04-16 15:50:10 +000013927/**
13928 * xmlSchemaRegisterAttributes:
13929 * @ctxt: a schema validation context
13930 * @attrs: a list of attributes
13931 *
13932 * Register the list of attributes as the set to be validated on that element
13933 *
13934 * Returns -1 in case of error, 0 otherwise
13935 */
13936static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013937xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
13938{
Daniel Veillard3646d642004-06-02 19:19:14 +000013939 xmlSchemaAttrStatePtr tmp;
13940
13941 ctxt->attr = NULL;
13942 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013943 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013944 if ((attrs->ns != NULL) &&
13945 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
13946 attrs = attrs->next;
13947 continue;
13948 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013949 tmp = (xmlSchemaAttrStatePtr)
13950 xmlMalloc(sizeof(xmlSchemaAttrState));
13951 if (tmp == NULL) {
13952 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
13953 return (-1);
13954 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013955 tmp->attr = attrs;
13956 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
13957 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013958 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013959 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013960 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013961 else
13962 ctxt->attrTop->next = tmp;
13963 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013964 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013965 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013966 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000013967}
13968
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013969#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000013970/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013971 * xmlSchemaValidateCheckNodeList
13972 * @nodelist: the list of nodes
13973 *
13974 * Check the node list is only made of text nodes and entities pointing
13975 * to text nodes
13976 *
13977 * Returns 1 if true, 0 if false and -1 in case of error
13978 */
13979static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013980xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
13981{
Daniel Veillard4255d502002-04-16 15:50:10 +000013982 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013983 if (nodelist->type == XML_ENTITY_REF_NODE) {
13984 TODO /* implement recursion in the entity content */
13985 }
13986 if ((nodelist->type != XML_TEXT_NODE) &&
13987 (nodelist->type != XML_COMMENT_NODE) &&
13988 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000013989 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013990 return (0);
13991 }
13992 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013993 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013994 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013995}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013996#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013997
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013998static void
13999xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14000{
14001 int i, nbItems;
14002 xmlSchemaTypePtr item, *items;
14003
14004
14005 /*
14006 * During the Assemble of the schema ctxt->curItems has
14007 * been filled with the relevant new items. Fix those up.
14008 */
14009 nbItems = ctxt->assemble->nbItems;
14010 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14011
14012 for (i = 0; i < nbItems; i++) {
14013 item = items[i];
14014 switch (item->type) {
14015 case XML_SCHEMA_TYPE_ATTRIBUTE:
14016 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14017 break;
14018 case XML_SCHEMA_TYPE_ELEMENT:
14019 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14020 NULL, NULL, NULL);
14021 break;
14022 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14023 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14024 ctxt, NULL);
14025 break;
14026 case XML_SCHEMA_TYPE_GROUP:
14027 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14028 default:
14029 break;
14030 }
14031 }
14032 /*
14033 * Circularity checks.
14034 */
14035 for (i = 0; i < nbItems; i++) {
14036 item = items[i];
14037 switch (item->type) {
14038 case XML_SCHEMA_TYPE_GROUP:
14039 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14040 break;
14041 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14042 xmlSchemaCheckAttributeGroupCircular(
14043 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14044 break;
14045 default:
14046 break;
14047 }
14048 }
14049 /*
14050 * Fixup for all other item.
14051 * TODO: Hmm, not sure if starting from complex/simple types,
14052 * all subsequent items will be reached.
14053 */
14054 for (i = 0; i < nbItems; i++) {
14055 item = items[i];
14056 switch (item->type) {
14057 case XML_SCHEMA_TYPE_SIMPLE:
14058 case XML_SCHEMA_TYPE_COMPLEX:
14059 xmlSchemaTypeFixup(item, ctxt, NULL);
14060 break;
14061 default:
14062 break;
14063 }
14064 }
14065 /*
14066 * Check facet values. Note that facets are
14067 * hold by complex and simple type components only.
14068 */
14069 for (i = 0; i < nbItems; i++) {
14070 item = items[i];
14071 switch (item->type) {
14072 case XML_SCHEMA_TYPE_SIMPLE:
14073 case XML_SCHEMA_TYPE_COMPLEX:
14074 xmlSchemaCheckDefaults(item, ctxt, NULL);
14075 break;
14076 default:
14077 break;
14078 }
14079 }
14080 /*
14081 * Build the content model for complex types.
14082 */
14083 for (i = 0; i < nbItems; i++) {
14084 item = items[i];
14085 switch (item->type) {
14086 case XML_SCHEMA_TYPE_COMPLEX:
14087 xmlSchemaBuildContentModel(item, ctxt, NULL);
14088 break;
14089 default:
14090 break;
14091 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014092 }
14093 /*
14094 * Validate value contraint values.
14095 */
14096 for (i = 0; i < nbItems; i++) {
14097 item = items[i];
14098 switch (item->type) {
14099 case XML_SCHEMA_TYPE_ATTRIBUTE:
14100 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14101 break;
14102 case XML_SCHEMA_TYPE_ELEMENT:
14103 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14104 break;
14105 default:
14106 break;
14107 }
14108 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014109}
14110
14111/**
14112 * xmlSchemaAssembleByLocation:
14113 * @pctxt: a schema parser context
14114 * @vctxt: a schema validation context
14115 * @schema: the existing schema
14116 * @node: the node that fired the assembling
14117 * @nsName: the namespace name of the new schema
14118 * @location: the location of the schema
14119 *
14120 * Expands an existing schema by an additional schema.
14121 *
14122 * Returns 0 if the new schema is correct, a positive error code
14123 * number otherwise and -1 in case of an internal or API error.
14124 */
14125static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014126xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14127 xmlSchemaPtr schema,
14128 xmlNodePtr node,
14129 const xmlChar *nsName,
14130 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014131{
14132 const xmlChar *targetNs, *oldtns;
14133 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014134 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014135 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014136 xmlSchemaParserCtxtPtr pctxt;
14137
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014138 /*
14139 * This should be used:
14140 * 1. on <import>(s)
14141 * 2. if requested by the validated instance
14142 * 3. if requested via the API
14143 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014144 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014145 return (-1);
14146 /*
14147 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014148 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014149 if ((vctxt->pctxt == NULL) &&
14150 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14151 xmlSchemaVErr(vctxt, node,
14152 XML_SCHEMAV_INTERNAL,
14153 "Internal error: xmlSchemaAssembleByLocation, "
14154 "failed to create a temp. parser context.\n",
14155 NULL, NULL);
14156 return (-1);
14157 }
14158 pctxt = vctxt->pctxt;
14159 /*
14160 * Set the counter to produce unique names for anonymous items.
14161 */
14162 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014163 /*
14164 * Acquire the schema document.
14165 */
14166 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14167 nsName, location, &doc, &targetNs, 0);
14168 if (ret != 0) {
14169 if (doc != NULL)
14170 xmlFreeDoc(doc);
14171 } else if (doc != NULL) {
14172 docElem = xmlDocGetRootElement(doc);
14173 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014174 * Create new assemble info.
14175 */
14176 if (pctxt->assemble == NULL) {
14177 pctxt->assemble = xmlSchemaNewAssemble();
14178 if (pctxt->assemble == NULL) {
14179 xmlSchemaVErrMemory(vctxt,
14180 "Memory error: xmlSchemaAssembleByLocation, "
14181 "allocating assemble info", NULL);
14182 xmlFreeDoc(doc);
14183 return (-1);
14184 }
14185 }
14186 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014187 * Save and reset the context & schema.
14188 */
14189 oldflags = schema->flags;
14190 oldtns = schema->targetNamespace;
14191 olddoc = schema->doc;
14192
14193 xmlSchemaClearSchemaDefaults(schema);
14194 schema->targetNamespace = targetNs;
14195 /* schema->nbCurItems = 0; */
14196 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014197 pctxt->ctxtType = NULL;
14198 pctxt->parentItem = NULL;
14199
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014200 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14201 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014202 xmlSchemaPostSchemaAssembleFixup(pctxt);
14203 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014204 * Set the counter of items.
14205 */
14206 schema->counter = pctxt->counter;
14207 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014208 * Free the list of assembled components.
14209 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014210 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014211 /*
14212 * Restore the context & schema.
14213 */
14214 schema->flags = oldflags;
14215 schema->targetNamespace = oldtns;
14216 schema->doc = olddoc;
14217 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014218 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014219 return (ret);
14220}
14221
14222/**
14223 * xmlSchemaAssembleByXSIAttr:
14224 * @vctxt: a schema validation context
14225 * @xsiAttr: an xsi attribute
14226 * @noNamespace: whether a schema with no target namespace is exptected
14227 *
14228 * Expands an existing schema by an additional schema using
14229 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14230 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14231 * must be set to 1.
14232 *
14233 * Returns 0 if the new schema is correct, a positive error code
14234 * number otherwise and -1 in case of an internal or API error.
14235 */
14236static int
14237xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14238 xmlAttrPtr xsiAttr,
14239 int noNamespace)
14240{
14241 xmlChar *value;
14242 const xmlChar *cur, *end;
14243 const xmlChar *nsname = NULL, *location;
14244 int count = 0;
14245 int ret = 0;
14246
14247 if (xsiAttr == NULL) {
14248 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14249 NULL, NULL,
14250 "Internal error: xmlSchemaAssembleByXSIAttr, "
14251 "bad arguments", NULL);
14252 return (-1);
14253 }
14254 /*
14255 * Parse the value; we will assume an even number of values
14256 * to be given (this is how Xerces and XSV work).
14257 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014258 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014259 cur = value;
14260 do {
14261 if (noNamespace != 1) {
14262 /*
14263 * Get the namespace name.
14264 */
14265 while (IS_BLANK_CH(*cur))
14266 cur++;
14267 end = cur;
14268 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14269 end++;
14270 if (end == cur)
14271 break;
14272 count++;
14273 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14274 cur = end;
14275 }
14276 /*
14277 * Get the URI.
14278 */
14279 while (IS_BLANK_CH(*cur))
14280 cur++;
14281 end = cur;
14282 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14283 end++;
14284 if (end == cur)
14285 break;
14286 count++;
14287 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014288 cur = end;
14289 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014290 xsiAttr->parent, nsname, location);
14291 if (ret == -1) {
14292 xmlSchemaVCustomErr(vctxt,
14293 XML_SCHEMAV_INTERNAL,
14294 (xmlNodePtr) xsiAttr, NULL,
14295 "Internal error: xmlSchemaAssembleByXSIAttr, "
14296 "assembling schemata", NULL);
14297 if (value != NULL)
14298 xmlFree(value);
14299 return (-1);
14300 }
14301 } while (*cur != 0);
14302 if (value != NULL)
14303 xmlFree(value);
14304 return (ret);
14305}
14306
14307/**
14308 * xmlSchemaAssembleByXSIElem:
14309 * @vctxt: a schema validation context
14310 * @elem: an element node possibly holding xsi attributes
14311 * @noNamespace: whether a schema with no target namespace is exptected
14312 *
14313 * Assembles an existing schema by an additional schema using
14314 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14315 * of the given @elem.
14316 *
14317 * Returns 0 if the new schema is correct, a positive error code
14318 * number otherwise and -1 in case of an internal or API error.
14319 */
14320static int
14321xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14322 xmlNodePtr elem)
14323{
14324 int ret = 0, retNs = 0;
14325 xmlAttrPtr attr;
14326
14327 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14328 if (attr != NULL) {
14329 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14330 if (retNs == -1)
14331 return (-1);
14332 }
14333 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14334 if (attr != NULL) {
14335 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14336 if (ret == -1)
14337 return (-1);
14338 }
14339 if (retNs != 0)
14340 return (retNs);
14341 else
14342 return (ret);
14343}
14344
Daniel Veillard4255d502002-04-16 15:50:10 +000014345/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014346 * xmlSchemaValidateCallback:
14347 * @ctxt: a schema validation context
14348 * @name: the name of the element detected (might be NULL)
14349 * @type: the type
14350 *
14351 * A transition has been made in the automata associated to an element
14352 * content model
14353 */
14354static void
14355xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014356 const xmlChar * name ATTRIBUTE_UNUSED,
14357 xmlSchemaTypePtr type, xmlNodePtr node)
14358{
Daniel Veillard4255d502002-04-16 15:50:10 +000014359 xmlSchemaTypePtr oldtype = ctxt->type;
14360 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014361
Daniel Veillard4255d502002-04-16 15:50:10 +000014362#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014363 xmlGenericError(xmlGenericErrorContext,
14364 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014365 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014366#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014367 /*
14368 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14369 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014370 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014371 ctxt->node = node;
14372 ctxt->cur = node->children;
14373 /*
14374 * Assemble new schemata using xsi.
14375 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014376 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014377 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014378
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014379 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14380 if (ret == -1) {
14381 xmlSchemaVCustomErr(ctxt,
14382 XML_SCHEMAV_INTERNAL,
14383 ctxt->node, NULL,
14384 "Internal error: xmlSchemaValidateElement, "
14385 "assembling schema by xsi", NULL);
14386 return;
14387 }
14388 /*
14389 * NOTE: We won't react on schema parser errors here.
14390 * TODO: But a warning would be nice.
14391 */
14392 }
14393 switch (type->type) {
14394 case XML_SCHEMA_TYPE_ELEMENT: {
14395 /*
14396 * NOTE: The build of the content model
14397 * (xmlSchemaBuildAContentModel) ensures that the element
14398 * declaration (and not a reference to it) will be given.
14399 */
14400 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14401 /*
14402 * This is paranoid coding ;-)... it should not
14403 * happen here any more.
14404 */
14405 xmlSchemaVCustomErr(ctxt,
14406 XML_SCHEMAV_INTERNAL,
14407 node, NULL,
14408 "Internal error: xmlSchemaValidateCallback, "
14409 "element declaration 'reference' encountered, "
14410 "but an element declaration was expected",
14411 NULL);
14412 return;
14413 }
14414 xmlSchemaValidateElementByDeclaration(ctxt,
14415 (xmlSchemaElementPtr) type);
14416 break;
14417 }
14418 case XML_SCHEMA_TYPE_ANY:
14419 xmlSchemaValidateElementByWildcard(ctxt, type);
14420 break;
14421 default:
14422 break;
14423 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014424 ctxt->type = oldtype;
14425 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014426}
Daniel Veillard4255d502002-04-16 15:50:10 +000014427
Daniel Veillard01fa6152004-06-29 17:04:39 +000014428/**
14429 * xmlSchemaValidateSimpleTypeValue:
14430 * @ctxt: a schema validation context
14431 * @value: the value to be validated
14432 * @fireErrors: shall errors be reported?
14433 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014434 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014435 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014436 *
14437 * Validates a value by the given type (user derived or built-in).
14438 *
14439 * Returns 0 if the value is valid, a positive error code
14440 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014441 */
14442static int
14443xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014444 xmlSchemaTypePtr type,
14445 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014446 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014447 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014448 int normalize,
14449 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014450{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014451 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014452 int ret = 0;
14453 xmlChar *normValue = NULL;
14454 int wtsp;
14455
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014456 node = ctxt->node;
14457 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014458 wtsp = ctxt->valueWS;
14459 /*
14460 * Normalize the value.
14461 */
14462 if (normalize &&
14463 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14464 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14465
14466 if ((norm != -1) && (norm > ctxt->valueWS)) {
14467 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14468 normValue = xmlSchemaCollapseString(value);
14469 else
14470 normValue = xmlSchemaWhiteSpaceReplace(value);
14471 ctxt->valueWS = norm;
14472 if (normValue != NULL)
14473 value = (const xmlChar *) normValue;
14474 }
14475 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014476 /*
14477 * The nodes of a content must be checked only once,
14478 * this is not working since list types will fire this
14479 * multiple times.
14480 */
14481 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14482 xmlNodePtr cur = ctxt->cur;
14483
14484 do {
14485 switch (cur->type) {
14486 case XML_TEXT_NODE:
14487 case XML_CDATA_SECTION_NODE:
14488 case XML_PI_NODE:
14489 case XML_COMMENT_NODE:
14490 case XML_XINCLUDE_START:
14491 case XML_XINCLUDE_END:
14492 break;
14493 case XML_ENTITY_REF_NODE:
14494 case XML_ENTITY_NODE:
14495 /* TODO: Scour the entities for illegal nodes. */
14496 TODO break;
14497 case XML_ELEMENT_NODE: {
14498 /* NOTE: Changed to an internal error, since the
14499 * existence of an element node will be already checked in
14500 * xmlSchemaValidateElementBySimpleType and in
14501 * xmlSchemaValidateElementByComplexType.
14502 */
14503 xmlSchemaVCustomErr(ctxt,
14504 XML_SCHEMAV_INTERNAL,
14505 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14506 node, type,
14507 "Element '%s' found in simple type content",
14508 cur->name);
14509 return (XML_SCHEMAV_INTERNAL);
14510 }
14511 case XML_ATTRIBUTE_NODE:
14512 case XML_DOCUMENT_NODE:
14513 case XML_DOCUMENT_TYPE_NODE:
14514 case XML_DOCUMENT_FRAG_NODE:
14515 case XML_NOTATION_NODE:
14516 case XML_HTML_DOCUMENT_NODE:
14517 case XML_DTD_NODE:
14518 case XML_ELEMENT_DECL:
14519 case XML_ATTRIBUTE_DECL:
14520 case XML_ENTITY_DECL:
14521 case XML_NAMESPACE_DECL:
14522#ifdef LIBXML_DOCB_ENABLED
14523 case XML_DOCB_DOCUMENT_NODE:
14524#endif
14525 xmlSchemaVCustomErr(ctxt,
14526 XML_SCHEMAV_INTERNAL,
14527 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14528 node, NULL,
14529 "Node of unexpected type found in simple type content",
14530 NULL);
14531 return (XML_SCHEMAV_INTERNAL);
14532 }
14533 cur = cur->next;
14534 } while (cur != NULL);
14535 }
14536
William M. Brack2f2a6632004-08-20 23:09:47 +000014537 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14538 xmlSchemaTypePtr base, anyType;
14539
14540 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14541
14542 base = type->baseType;
14543 while ((base != NULL) &&
14544 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14545 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14546 (base != anyType)) {
14547 base = base->baseType;
14548 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014549 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014550 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014551 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014552 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14553 "validating complex type '%s'\n",
14554 type->name, NULL);
14555 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14556 /*
14557 * Check facets.
14558 */
14559 /*
14560 * This is somehow not nice, since if an error occurs
14561 * the reported type will be the complex type; the spec
14562 * wants a simple type to be created on the complex type
14563 * if it has a simple content. For now we have to live with
14564 * it.
14565 */
14566 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14567 value, 0, fireErrors);
14568 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014569 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014570 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14571 "validating facets of complex type '%s'\n",
14572 type->name, NULL);
14573 } else if (ret > 0) {
14574 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014575 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014576 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014577 }
14578 }
14579 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014580
14581 if (ctxt->value != NULL) {
14582 xmlSchemaFreeValue(ctxt->value);
14583 ctxt->value = NULL;
14584 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014585 /*
14586 * STREAM-READ-CHILDREN.
14587 */
14588 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014589 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014590 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14591 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14592 else
14593 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014594 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014595 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014596 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014597 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014598 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014599 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014600 }
14601 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14602 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14603 * a literal in the ·lexical space· of {base type definition}
14604 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014605 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014606 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014607 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014608 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014609 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014610 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014611 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014612 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014613 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014614 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014615 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014616 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014617 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014618 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014619 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14620 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014621 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014622 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014623 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014624 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014625 type->name, NULL);
14626 } else if (ret > 0) {
14627 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014628 /*
14629 Disabled, since the facet validation already reports errors.
14630 if (fireErrors)
14631 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14632 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014633 }
14634 }
14635 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14636
14637 xmlSchemaTypePtr tmpType;
14638 const xmlChar *cur, *end;
14639 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014640 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014641
14642 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14643 * of white space separated tokens, each of which ·match·es a literal
14644 * in the ·lexical space· of {item type definition}
14645 */
14646
Daniel Veillardc0826a72004-08-10 14:17:33 +000014647 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014648 cur = value;
14649 do {
14650 while (IS_BLANK_CH(*cur))
14651 cur++;
14652 end = cur;
14653 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14654 end++;
14655 if (end == cur)
14656 break;
14657 tmp = xmlStrndup(cur, end - cur);
14658 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014659 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014660 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014661 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014662 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014663 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14664 "validating an item of list simple type '%s'\n",
14665 type->name, NULL);
14666 break;
14667 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014668 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014669 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014670 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014671 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014672 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014673 cur = end;
14674 } while (*cur != 0);
14675 /*
14676 * Check facets.
14677 */
14678 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014679 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014680 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014681 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014682 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014683 } else if ((ret == 0) && (applyFacets)) {
14684 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14685 value, len, fireErrors);
14686 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014687 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014688 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14689 "validating facets of list simple type '%s'\n",
14690 type->name, NULL);
14691 } else if (ret > 0) {
14692 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014693 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014694 Disabled, since the facet validation already reports errors.
14695 if (fireErrors)
14696 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014697 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014698 }
14699
Daniel Veillard01fa6152004-06-29 17:04:39 +000014700 }
14701 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14702 xmlSchemaTypeLinkPtr memberLink;
14703
14704 /*
14705 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14706 * not apply directly; however, the normalization behavior of ·union·
14707 * types is controlled by the value of whiteSpace on that one of the
14708 * ·memberTypes· against which the ·union· is successfully validated.
14709 *
14710 * This means that the value is normalized by the first validating
14711 * member type, then the facets of the union type are applied. This
14712 * needs changing of the value!
14713 */
14714
14715 /*
14716 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14717 * literal in the ·lexical space· of at least one member of
14718 * {member type definitions}
14719 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014720#ifdef DEBUG_UNION_VALIDATION
14721 printf("Union ST : '%s'\n", (const char *) type->name);
14722 printf(" fireErrors : %d\n", fireErrors);
14723 printf(" applyFacets: %d\n", applyFacets);
14724#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014725 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14726 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014727 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014728 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014729 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014730 type->name, NULL);
14731 ret = -1;
14732 }
14733 if (ret == 0) {
14734 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014735 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14736 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014737 if ((ret <= 0) || (ret == 0))
14738 break;
14739 memberLink = memberLink->next;
14740 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014741 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014742 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014743 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014744 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014745 type->name, NULL);
14746 } else if (ret > 0) {
14747 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014748 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014749 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014750 }
14751 }
14752 /*
14753 * Apply facets (pattern, enumeration).
14754 */
14755 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14756 int mws;
14757 /*
14758 * The normalization behavior of ·union· types is controlled by
14759 * the value of whiteSpace on that one of the ·memberTypes·
14760 * against which the ·union· is successfully validated.
14761 */
14762 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014763 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014764 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14765 "the value was already normalized for the union simple "
14766 "type '%s'.\n", type->name, NULL);
14767 }
14768 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14769 if (mws > ctxt->valueWS) {
14770 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14771 normValue = xmlSchemaCollapseString(value);
14772 else
14773 normValue = xmlSchemaWhiteSpaceReplace(value);
14774 if (normValue != NULL)
14775 value = (const xmlChar *) normValue;
14776 }
14777
14778 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14779 value, 0, fireErrors);
14780 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014781 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014782 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14783 "validating facets of union simple type '%s'\n",
14784 type->name, NULL);
14785 } else if (ret > 0) {
14786 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14787 /*
14788 if (fireErrors)
14789 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14790 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014791 }
14792 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014793 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014794 ctxt->valueWS = wtsp;
14795 if (normValue != NULL)
14796 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014797 return (ret);
14798}
14799
14800/**
14801 * xmlSchemaValidateSimpleTypeElement:
14802 * @ctxt: a schema validation context
14803 * @node: the element node to be validated.
14804 *
14805 * Validate the element against a simple type.
14806 *
14807 * Returns 0 if the element is valid, a positive error code
14808 * number otherwise and -1 in case of an internal or API error.
14809 */
14810static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014811xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014812 xmlSchemaTypePtr type,
14813 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014814{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014815 xmlSchemaTypePtr oldtype;
14816 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014817 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014818 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014819 int ret = 0, retval = 0;
14820
Daniel Veillard01fa6152004-06-29 17:04:39 +000014821 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014822 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
14823 "Internal error: xmlSchemaValidateElementBySimpleType, "
14824 "bad arguments", NULL);
14825 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014826 }
14827
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014828 oldtype = ctxt->type;
14829 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014830 /*
14831 * cvc-type: 3.1.2 The element information item must have no element
14832 * information item [children].
14833 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014834 /*
14835 * STREAM: Child nodes are processed.
14836 */
14837 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014838 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014839 /*
14840 * TODO: Entities, will they produce elements as well?
14841 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014842 if (cur->type == XML_ELEMENT_NODE) {
14843 xmlSchemaVCustomErr(ctxt,
14844 XML_SCHEMAV_CVC_TYPE_3_1_2,
14845 node, type,
14846 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014847 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014848 }
14849 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014850 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014851
Daniel Veillard01fa6152004-06-29 17:04:39 +000014852 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014853 * cvc-type 3.1.1:
14854 *
14855 * The attributes of must be empty, excepting those whose namespace name
14856 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
14857 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014858 */
14859 /*
14860 * STREAM: Attribute nodes are processed.
14861 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014862 attr = node->properties;
14863 while (attr != NULL) {
14864 if ((attr->ns == NULL) ||
14865 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
14866 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
14867 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
14868 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
14869 (!xmlStrEqual
14870 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014871 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014872 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
14873 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014874 }
14875 attr = attr->next;
14876 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014877 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014878 * This will skip validation if the type is 'anySimpleType' and
14879 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014880 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014881 if ((valSimpleContent == 1) &&
14882 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14883 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014884 xmlChar *value;
14885
14886 value = xmlNodeGetContent(node);
14887 /*
14888 * NOTE: This call will not check the content nodes, since
14889 * this should be checked here already.
14890 */
14891 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14892 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014893 if (value != NULL)
14894 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014895 if (retval != 0)
14896 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014897 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014898 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014899 return (ret);
14900}
Daniel Veillard4255d502002-04-16 15:50:10 +000014901
14902/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014903 * xmlSchemaValQNameAcquire:
14904 * @value: the lexical represantation of the QName value
14905 * @node: the node to search for the corresponding namespace declaration
14906 * @nsName: the resulting namespace name if found
14907 *
14908 * Checks that a value conforms to the lexical space of the type QName;
14909 * if valid, the corresponding namespace name is searched and retured
14910 * as a copy in @nsName. The local name is returned in @localName as
14911 * a copy.
14912 *
14913 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14914 * namespace declaration was found in scope; -1 in case of an internal or
14915 * API error.
14916 */
14917static int
14918xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14919 xmlChar **nsName, xmlChar **localName)
14920{
14921 int ret;
14922 xmlChar *local = NULL;
14923
14924 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14925 return (-1);
14926 *nsName = NULL;
14927 *localName = NULL;
14928 ret = xmlValidateQName(value, 1);
14929 if (ret == 0) {
14930 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014931 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014932
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014933 /*
14934 * NOTE: xmlSplitQName2 will return a duplicated
14935 * string.
14936 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014937 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014938 if (local == NULL)
14939 local = xmlStrdup(value);
14940 ns = xmlSearchNs(node->doc, node, prefix);
14941 /*
14942 * A namespace need not to be found if the prefix is NULL.
14943 */
14944 if (ns != NULL) {
14945 /*
14946 * TODO: Is it necessary to duplicate the URI here?
14947 */
14948 *nsName = xmlStrdup(ns->href);
14949 } else if (prefix != NULL) {
14950 xmlFree(prefix);
14951 if (local != NULL)
14952 xmlFree(local);
14953 return (2);
14954 }
14955 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014956 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014957 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014958 } else
14959 return (1);
14960 return (ret);
14961}
14962
14963/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014964 * xmlSchemaHasElemContent:
14965 * @node: the node
14966 *
14967 * Scours the content of the given node for element
14968 * nodes.
14969 *
14970 * Returns 1 if an element node is found,
14971 * 0 otherwise.
14972 */
14973static int
14974xmlSchemaHasElemContent(xmlNodePtr node)
14975{
14976 if (node == NULL)
14977 return (0);
14978 node = node->children;
14979 while (node != NULL) {
14980 if (node->type == XML_ELEMENT_NODE)
14981 return (1);
14982 node = node->next;
14983 }
14984 return (0);
14985}
14986/**
14987 * xmlSchemaHasElemOrCharContent:
14988 * @node: the node
14989 *
14990 * Scours the content of the given node for element
14991 * and character nodes.
14992 *
14993 * Returns 1 if an element or character node is found,
14994 * 0 otherwise.
14995 */
14996static int
14997xmlSchemaHasElemOrCharContent(xmlNodePtr node)
14998{
14999 if (node == NULL)
15000 return (0);
15001 node = node->children;
15002 while (node != NULL) {
15003 switch (node->type) {
15004 case XML_ELEMENT_NODE:
15005 /*
15006 * TODO: Ask Daniel if these are all character nodes.
15007 */
15008 case XML_TEXT_NODE:
15009 case XML_CDATA_SECTION_NODE:
15010 /*
15011 * TODO: How XML_ENTITY_NODEs evaluated?
15012 */
15013 case XML_ENTITY_REF_NODE:
15014 case XML_ENTITY_NODE:
15015 return (1);
15016 break;
15017 default:
15018 break;
15019 }
15020 node = node->next;
15021 }
15022 return (0);
15023}
15024
15025
15026/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015027 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015028 * @ctxt: a schema validation context
15029 * @node: the top node.
15030 *
15031 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015032 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015033 *
15034 * Returns 0 if the element is schemas valid, a positive error code
15035 * number otherwise and -1 in case of internal or API error.
15036 */
15037static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015038xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15039 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015040{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015041 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015042 int ret = 0;
15043 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015044 xmlAttrPtr attr;
15045 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015046 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015047
15048 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015049 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15050 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015051 * Note that @elemDecl will be the declaration and never the
15052 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015053 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015054
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015055 if (ctxt == NULL) {
15056 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15057 "Internal error: xmlSchemaValidateElementByDeclaration, "
15058 "bad arguments.\n",
15059 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015060 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015061 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015062
15063 elem = ctxt->node;
15064
15065 /*
15066 * cvc-elt (3.3.4) : 1
15067 */
15068 if (elemDecl == NULL) {
15069 xmlSchemaVCustomErr(ctxt,
15070 XML_SCHEMAV_CVC_ELT_1,
15071 elem, NULL,
15072 "No matching declaration available", NULL);
15073 return (ctxt->err);
15074 }
15075 /*
15076 * cvc-elt (3.3.4) : 2
15077 */
15078 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15079 xmlSchemaVCustomErr(ctxt,
15080 XML_SCHEMAV_CVC_ELT_2,
15081 elem, NULL,
15082 "The element declaration is abstract", NULL);
15083 return (ctxt->err);
15084 }
15085
15086 /*
15087 * cvc-elt (3.3.4) : 3
15088 * Handle 'xsi:nil'.
15089 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015090
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015091 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015092 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015093 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15094 ctxt->node = (xmlNodePtr) attr;
15095 ctxt->cur = attr->children;
15096 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15097 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15098 BAD_CAST attrValue, 1, 1, 1, 1);
15099 ctxt->node = elem;
15100 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15101 if (ret < 0) {
15102 xmlSchemaVCustomErr(ctxt,
15103 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015104 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015105 "Internal error: xmlSchemaValidateElementByDeclaration, "
15106 "validating the attribute 'xsi:nil'", NULL);
15107 if (attrValue != NULL)
15108 xmlFree(attrValue);
15109 return (-1);
15110 }
15111 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015112 /*
15113 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015114 */
15115 xmlSchemaVCustomErr(ctxt,
15116 XML_SCHEMAV_CVC_ELT_3_1,
15117 elem, NULL,
15118 "The element is not 'nillable'", NULL);
15119 } else {
15120 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015121 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015122 ret = 0;
15123 /*
15124 * cvc-elt (3.3.4) : 3.2.1
15125 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015126 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15127 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015128 xmlSchemaVCustomErr(ctxt,
15129 XML_SCHEMAV_CVC_ELT_3_2_1,
15130 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015131 elem, (xmlSchemaTypePtr) elemDecl,
15132 "The 'nilled' element must have no character or "
15133 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015134 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15135 }
15136 /*
15137 * cvc-elt (3.3.4) : 3.2.2
15138 */
15139 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15140 (elemDecl->value != NULL)) {
15141 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15142 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015143 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015144 "There is a fixed value constraint defined for "
15145 "the 'nilled' element", NULL);
15146 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15147 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015148 if (ret == 0)
15149 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015150 }
15151 }
15152 if (attrValue != NULL)
15153 xmlFree(attrValue);
15154 }
15155
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015156
15157 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015158 /*
15159 * cvc-elt (3.3.4) : 4
15160 * Handle 'xsi:type'.
15161 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015162
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015163 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15164 if (attr != NULL) {
15165 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015166
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015167 /*
15168 * TODO: We should report a *warning* that the type was overriden
15169 * by the instance.
15170 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015171
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015172 /*
15173 * cvc-elt (3.3.4) : 4.1
15174 */
15175 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15176 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15177 &nsName, &local);
15178 if (ret < 0) {
15179 xmlSchemaVCustomErr(ctxt,
15180 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015181 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015182 "Internal error: xmlSchemaValidateElementByDeclaration, "
15183 "validating the attribute 'xsi:type'", NULL);;
15184 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015185 FREE_AND_NULL(nsName)
15186 FREE_AND_NULL(local)
15187 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015188 } else if (ret == 1) {
15189 xmlSchemaVSimpleTypeErr(ctxt,
15190 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15191 (xmlNodePtr) attr, attrValue,
15192 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15193 } else if (ret == 2) {
15194 xmlSchemaVCustomErr(ctxt,
15195 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15196 (xmlNodePtr) attr,
15197 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15198 "The QName value '%s' has no "
15199 "corresponding namespace declaration in scope",
15200 attrValue);
15201 } else {
15202 /*
15203 * cvc-elt (3.3.4) : 4.2
15204 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015205 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15206 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015207 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015208
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015209 xmlSchemaVCustomErr(ctxt,
15210 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015211 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015212 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15213 "The value %s does not resolve to a type "
15214 "definition",
15215 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15216 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015217 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015218 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015219 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015220 */
15221 }
15222 }
15223 FREE_AND_NULL(attrValue)
15224 FREE_AND_NULL(nsName)
15225 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015226 }
15227 /* TODO: Change the handling of missing types according to
15228 * the spec.
15229 */
15230 if (actualType == NULL) {
15231 xmlSchemaVComplexTypeErr(ctxt,
15232 XML_SCHEMAV_CVC_TYPE_1,
15233 elem, (xmlSchemaTypePtr) elemDecl,
15234 "The type definition is absent");
15235 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015236 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015237
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015238 /*
15239 * TODO: Since this should be already checked by the content model automaton,
15240 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15241 * has been changed to XML_SCHEMAV_INTERNAL.
15242 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015243 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015244 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015245 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015246 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015247 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015248 "Element %s: missing child %s\n",
15249 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015250 }
15251 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015252 }
15253 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015254 /*
15255 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015256 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015257 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015258 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015259 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015260 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015261 "Element %s: missing child %s found %s\n",
15262 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015263 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015264 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015265 */
15266 if (elemHasContent == -1)
15267 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15268 /*
15269 * cvc-elt (3.3.4) : 5
15270 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015271 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015272 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015273 * cvc-elt (3.3.4) : 5.1
15274 * If the declaration has a {value constraint},
15275 * the item has neither element nor character [children] and
15276 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015277 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015278 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15279 /*
15280 * cvc-elt (3.3.4) : 5.1.1
15281 * If the ·actual type definition· is a ·local type definition·
15282 * then the canonical lexical representation of the {value constraint}
15283 * value must be a valid default for the ·actual type definition· as
15284 * defined in Element Default Valid (Immediate) (§3.3.6).
15285 */
15286 /*
15287 * NOTE: 'local' above means types aquired by xsi:type.
15288 */
15289 ret = 0;
15290 if (actualType != elemDecl->subtypes) {
15291 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15292 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15293 elemDecl->value, NULL);
15294 if (ret < 0) {
15295 xmlSchemaVCustomErr(ctxt,
15296 XML_SCHEMAV_INTERNAL,
15297 elem, actualType,
15298 "Internal error: xmlSchemaValidateElementByDeclaration, "
15299 "validating a default value", NULL);
15300 return (-1);
15301 }
15302 }
15303 /*
15304 * cvc-elt (3.3.4) : 5.1.2
15305 * The element information item with the canonical lexical
15306 * representation of the {value constraint} value used as its
15307 * ·normalized value· must be ·valid· with respect to the
15308 * ·actual type definition· as defined by Element Locally Valid (Type)
15309 * (§3.3.4).
15310 */
15311 /*
15312 * Disable validation of the simple content, since it was already
15313 * done above.
15314 */
15315 if (ret == 0) {
15316 if (actualType != elemDecl->subtypes)
15317 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15318 else
15319 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15320 ctxt->node = elem;
15321 if (ret < 0) {
15322 xmlSchemaVCustomErr(ctxt,
15323 XML_SCHEMAV_INTERNAL,
15324 elem, actualType,
15325 "Internal error: xmlSchemaValidateElementByDeclaration, "
15326 "validating against the type", NULL);
15327 return (-1);
15328 }
15329 /*
15330 * PSVI: Create a text node on the instance element.
15331 */
15332 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15333 xmlNodePtr textChild;
15334
15335 textChild = xmlNewText(elemDecl->value);
15336 if (textChild == NULL) {
15337 xmlSchemaVCustomErr(ctxt,
15338 XML_SCHEMAV_INTERNAL,
15339 elem, actualType,
15340 "Internal error: xmlSchemaValidateElementByDeclaration, "
15341 "could not create a default text node for the instance",
15342 NULL);
15343 } else
15344 xmlAddChild(elem, textChild);
15345 }
15346 }
15347
15348 } else {
15349 /*
15350 * 5.2.1 The element information item must be ·valid· with respect
15351 * to the ·actual type definition· as defined by Element Locally
15352 * Valid (Type) (§3.3.4).
15353 */
15354 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15355 ctxt->node = elem;
15356 if (ret < 0) {
15357 xmlSchemaVCustomErr(ctxt,
15358 XML_SCHEMAV_INTERNAL,
15359 elem, actualType,
15360 "Internal error: xmlSchemaValidateElementByDeclaration, "
15361 "validating a default value", NULL);
15362 return (-1);
15363 }
15364 /*
15365 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15366 * not applied, all of the following must be true:
15367 */
15368
15369 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15370 /*
15371 * 5.2.2.1 The element information item must have no element
15372 * information item [children].
15373 *
15374 * TODO REDUNDANT: If the actual type exists, the above call to
15375 * xmlSchemaValidateElementByType will already check for element
15376 * nodes.
15377 */
15378 if (xmlSchemaHasElemContent(elem)) {
15379 xmlSchemaVCustomErr(ctxt,
15380 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15381 elem, (xmlSchemaTypePtr) elemDecl,
15382 "Elements in the content are not allowed if it is "
15383 "constrained by a fixed value", NULL);
15384 } else {
15385 /*
15386 * 5.2.2.2 The appropriate case among the following must
15387 * be true:
15388 */
15389
15390 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15391 xmlChar *value;
15392 /*
15393 * 5.2.2.2.1 If the {content type} of the ·actual type
15394 * definition· is mixed, then the *initial value* of the
15395 * item must match the canonical lexical representation
15396 * of the {value constraint} value.
15397 *
15398 * ... the *initial value* of an element information
15399 * item is the string composed of, in order, the
15400 * [character code] of each character information item in
15401 * the [children] of that element information item.
15402 */
15403 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15404 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15405 /*
15406 * TODO: Report invalid & expected values as well.
15407 * TODO: Implement the cononical stuff.
15408 */
15409 xmlSchemaVCustomErr(ctxt,
15410 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15411 elem, (xmlSchemaTypePtr) elemDecl,
15412 "The value does not match the cononical "
15413 "lexical representation of the fixed constraint",
15414 NULL);
15415 }
15416 if (value != NULL)
15417 xmlFree(value);
15418 } else if ((actualType->contentType ==
15419 XML_SCHEMA_CONTENT_SIMPLE) ||
15420 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15421 xmlChar *value;
15422
15423 /*
15424 * 5.2.2.2.2 If the {content type} of the ·actual type
15425 * definition· is a simple type definition, then the
15426 * *actual value* of the item must match the canonical
15427 * lexical representation of the {value constraint} value.
15428 */
15429 /*
15430 * TODO: *actual value* is the normalized value, impl. this.
15431 * TODO: Report invalid & expected values as well.
15432 * TODO: Implement the cononical stuff.
15433 *
15434 */
15435 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15436 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15437 xmlSchemaVCustomErr(ctxt,
15438 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15439 elem, (xmlSchemaTypePtr) elemDecl,
15440 "The normalized value does not match the cononical "
15441 "lexical representation of the fixed constraint",
15442 NULL);
15443 }
15444 if (value != NULL)
15445 xmlFree(value);
15446
15447 }
15448 /*
15449 * TODO: What if the content type is not 'mixed' or simple?
15450 */
15451
15452 }
15453
15454 }
15455 }
15456
15457 /*
15458 * TODO: 6 The element information item must be ·valid· with respect to each of
15459 * the {identity-constraint definitions} as per Identity-constraint
15460 * Satisfied (§3.11.4).
15461 */
15462
15463 /*
15464 * TODO: 7 If the element information item is the ·validation root·, it must be
15465 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15466 */
15467
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015468 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015469}
15470
Daniel Veillard4255d502002-04-16 15:50:10 +000015471/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015472 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015473 * @ctxt: a schema validation context
15474 * @node: the top node.
15475 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015476 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15477 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015478 *
15479 * Returns 0 if the element is valid, a positive error code
15480 * number otherwise and -1 in case of an internal error.
15481 */
15482static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015483xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15484 xmlSchemaWildcardPtr wild,
15485 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015486{
15487 const xmlChar *uri;
15488 int ret = 0;
15489 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015490
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015491 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015492 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15493 if (ret == -1) {
15494 xmlSchemaVCustomErr(ctxt,
15495 XML_SCHEMAV_INTERNAL,
15496 ctxt->node, NULL,
15497 "Internal error: xmlSchemaValidateElement, "
15498 "assembling schema by xsi", NULL);
15499 return (-1);
15500 }
15501 /*
15502 * NOTE: We won't react on schema parser errors here.
15503 * TODO: But a warning would be nice.
15504 */
15505 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015506 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15507 xmlSchemaElementPtr decl = NULL;
15508
15509 if (node->ns != NULL)
15510 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15511 node->name, node->ns->href, NULL);
15512 else
15513 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15514 if (decl != NULL) {
15515 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015516 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015517 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015518 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015519 "Internal error: xmlSchemaValidateAnyInternal, "
15520 "validating an element in the context of a wildcard.",
15521 NULL, NULL);
15522 } else if (ret > 0)
15523 return (ret);
15524 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15525 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015526 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015527 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015528 return (ctxt->err);
15529 }
15530 }
15531 if (node->children != NULL) {
15532 child = node->children;
15533 do {
15534 if (child->type == XML_ELEMENT_NODE) {
15535 if (child->ns != NULL)
15536 uri = child->ns->href;
15537 else
15538 uri = NULL;
15539 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015540 /* TODO: error code. */
15541 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015542 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015543 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015544 return (ctxt->err);
15545 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015546 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15547 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015548 if (ret != 0)
15549 return (ret);
15550 }
15551 child = child->next;
15552 } while (child != NULL);
15553 }
15554 return (0);
15555}
15556
15557/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015558 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015559 * @ctxt: a schema validation context
15560 *
15561 * Returns 0 if the element is valid, a positive error code
15562 * number otherwise and -1 in case of an internal or API error.
15563 */
15564static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015565xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15566 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015567{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015568 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15569 (ctxt->node == NULL)) {
15570 xmlSchemaVCustomErr(ctxt,
15571 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15572 "Internal error: xmlSchemaValidateElementByWildcard, "
15573 "bad arguments", NULL);
15574 return (-1);
15575 }
15576 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15577 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015578}
15579
15580/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015581 * xmlSchemaValidateAnyTypeContent:
15582 * @ctxt: a schema validation context
15583 * @node: the current element
15584 *
15585 * This one validates the content of an element of the type
15586 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15587 * thus elements in the subtree will be validated, if a corresponding
15588 * declaration in the schema exists.
15589 *
15590 * Returns 0 if the element and its subtree is valid, a positive error code
15591 * otherwise and -1 in case of an internal or API error.
15592 */
15593static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015594xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15595 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015596{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015597 xmlSchemaTypePtr oldtype;
15598 xmlNodePtr top, cur;
15599 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015600 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015601
15602 if ((type == NULL) || (ctxt->node == NULL))
15603 return (-1);
15604
15605 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015606 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015607
15608 oldtype = ctxt->type;
15609 top = ctxt->node;
15610 /*
15611 * STREAM: Child nodes are processed.
15612 */
15613 cur = ctxt->node->children;
15614 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015615 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015616 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015617 /*
15618 * The process contents of the wildcard is "lax", thus
15619 * we need to validate the element if a declaration
15620 * exists.
15621 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015622 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015623 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015624 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015625 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015626 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015627 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015628 ctxt->node = cur;
15629 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15630 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015631 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015632 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015633 "Internal error: xmlSchemaValidateAnyTypeContent, "
15634 "validating an element in the context of a wildcard.",
15635 NULL, NULL);
15636 return (ret);
15637 } else if (ret > 0)
15638 return (ret);
15639 skipContent = 1;
15640 }
15641 }
15642 /*
15643 * Browse the full subtree, deep first.
15644 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015645 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015646 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015647 cur = cur->children;
15648 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015649 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015650 cur = cur->next;
15651 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015652 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015653 while (cur != top) {
15654 if (cur->parent != NULL)
15655 cur = cur->parent;
15656 if ((cur != top) && (cur->next != NULL)) {
15657 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015658 break;
15659 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015660 if (cur->parent == NULL) {
15661 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015662 break;
15663 }
15664 }
15665 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015666 if (cur == top)
15667 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015668 } else
15669 break;
15670 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015671 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015672 return (0);
15673}
15674
15675/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015676 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015677 * @ctxt: a schema validation context
15678 * @node: the top node.
15679 *
15680 * Validate the content of an element expected to be a complex type type
15681 * xmlschema-1.html#cvc-complex-type
15682 * Validation Rule: Element Locally Valid (Complex Type)
15683 *
15684 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015685 * number otherwise and -1 in case of internal or API error.
15686 * Note on reported errors: Although it might be nice to report
15687 * the name of the simple/complex type, used to validate the content
15688 * of a node, it is quite unnecessary: for global defined types
15689 * the local name of the element is equal to the NCName of the type,
15690 * for local defined types it makes no sense to output the internal
15691 * computed name of the type. TODO: Instead, one should attach the
15692 * struct of the type involved to the error handler - this allows
15693 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015694 */
15695static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015696xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015697 xmlSchemaTypePtr type,
15698 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015699{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015700 xmlSchemaTypePtr oldtype;
15701 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015702 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015703 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015704 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015705
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015706 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15707 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015708
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015709 oldtype = ctxt->type;
15710 ctxt->type = type;
15711 elem = ctxt->node;
15712
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015713 /*
15714 * Verify the attributes
15715 */
15716 /*
15717 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015718 */
15719 /* NOTE: removed, since a check for abstract is
15720 * done in the cvc-type constraint.
15721 *
15722 *
15723 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15724 * xmlSchemaVComplexTypeErr(ctxt,
15725 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15726 * elem, type,
15727 * "The type definition is abstract");
15728 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15729 *}
15730 */
15731
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015732 attrs = ctxt->attr;
15733 attrTop = ctxt->attrTop;
15734 /*
15735 * STREAM: Attribute nodes are processed.
15736 */
15737 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15738 xmlSchemaValidateAttributes(ctxt, elem, type);
15739 if (ctxt->attr != NULL)
15740 xmlSchemaFreeAttributeStates(ctxt->attr);
15741 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015742 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015743
15744 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015745 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015746 * model was defined. Somehow ->contModel is always not NULL
15747 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015748 * TODO: Check if the obove still occurs.
15749 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015750 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015751 case XML_SCHEMA_CONTENT_EMPTY: {
15752 /*
15753 * 1 If the {content type} is empty, then the element information
15754 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015755 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015756 /*
15757 * TODO: Is the entity stuff correct?
15758 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015759 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015760 xmlSchemaVComplexTypeErr(ctxt,
15761 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015762 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015763 "Character or element content is not allowed, "
15764 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015765 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015766 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015767 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015768 case XML_SCHEMA_CONTENT_MIXED:
15769 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015770 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015771 /*
15772 * The type has 'anyType' as its base and no content model
15773 * is defined -> use 'anyType' as the type to validate
15774 * against.
15775 */
15776 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15777 /* TODO: Handle -1. */
15778 break;
15779 }
15780 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015781 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015782 {
15783 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015784
15785 /*
15786 * Content model check initialization.
15787 */
15788 if (type->contModel != NULL) {
15789 oldregexp = ctxt->regexp;
15790 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15791 (xmlRegExecCallbacks)
15792 xmlSchemaValidateCallback, ctxt);
15793#ifdef DEBUG_AUTOMATA
15794 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15795#endif
15796 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015797 /*
15798 * STREAM: Children are processed.
15799 */
15800 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015801 while (child != NULL) {
15802 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015803 if (child->ns != NULL)
15804 nsUri = child->ns->href;
15805 else
15806 nsUri = NULL;
15807 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015808 child->name, nsUri, child);
15809 /*
15810 * URGENT TODO: Could we anchor an error report
15811 * here to notify of invalid elements?
15812 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015813#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000015814 if (ret < 0)
15815 xmlGenericError(xmlGenericErrorContext,
15816 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000015817 else
15818 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015819 " --> %s\n", child->name);
15820#endif
15821 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
15822 /*
15823 * TODO: Ask Daniel if this are all character nodes.
15824 */
15825 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
15826 (child->type == XML_ENTITY_NODE) ||
15827 (child->type == XML_ENTITY_REF_NODE) ||
15828 (child->type == XML_CDATA_SECTION_NODE))) {
15829 /*
15830 * 2.3 If the {content type} is element-only, then the
15831 * element information item has no character information
15832 * item [children] other than those whose [character
15833 * code] is defined as a white space in [XML 1.0 (Second
15834 * Edition)].
15835 */
William M. Brack2f2a6632004-08-20 23:09:47 +000015836 xmlSchemaVComplexTypeErr(ctxt,
15837 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015838 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015839 "Character content is not allowed, "
15840 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015841 break;
15842 }
15843 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015844 }
15845 /*
15846 * Content model check finalization.
15847 */
15848 if (type->contModel != NULL) {
15849 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
15850#ifdef DEBUG_AUTOMATA
15851 xmlGenericError(xmlGenericErrorContext,
15852 "====> %s : %d\n", elem->name, ret);
15853#endif
15854 if (ret == 0) {
15855 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15856 elem, type, "The element content is not valid", NULL);
15857 } else if (ret < 0) {
15858 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15859 elem, type, "The element content is not valid", NULL);
15860#ifdef DEBUG_CONTENT
15861 } else {
15862 xmlGenericError(xmlGenericErrorContext,
15863 "Element %s content check succeeded\n",
15864 elem->name);
15865
15866#endif
15867 }
15868 xmlRegFreeExecCtxt(ctxt->regexp);
15869 ctxt->regexp = oldregexp;
15870 }
15871 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015872 break;
15873 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015874 case XML_SCHEMA_CONTENT_BASIC:
15875 /*
15876 * If the simple content was already validated
15877 * (e.g. a default value), the content need not
15878 * to be validated again.
15879 */
15880 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015881 xmlChar *value = NULL;
15882 /*
15883 * We hit a complexType with a simpleContent resolving
15884 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000015885 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015886 /*
15887 * 2.2 If the {content type} is a simple type definition,
15888 * then the element information item has no element
15889 * information item [children], and the ·normalized value·
15890 * of the element information item is ·valid· with respect
15891 * to that simple type definition as defined by String
15892 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015893 */
15894 /*
15895 * STREAM: Children are processed.
15896 */
15897 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015898 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015899 /*
15900 * TODO: Could the entity stuff produce elements
15901 * as well?
15902 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015903 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015904 xmlSchemaVComplexTypeErr(ctxt,
15905 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015906 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015907 "Element content is not allowed, because "
15908 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015909 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15910 break;
15911 }
15912 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015913 }
15914 ctxt->node = elem;
15915 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015916 if (ret == 0) {
15917 /*
15918 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000015919 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015920 /*
15921 * STREAM: Children are processed.
15922 */
15923 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015924 value = NULL;
15925 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015926 value = xmlNodeGetContent(elem);
15927 /*
15928 * URGENT TODO: Should facets for the simple type validation be
15929 * disabled, if the derivation of facets for complex types
15930 * is implemented?
15931 */
15932 /*
15933 * NOTE: This call won't check the correct types of the
15934 * content nodes, since this should be done here.
15935 */
15936 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015937 if (ret > 0) {
15938 /*
15939 * NOTE: Although an error will be reported by
15940 * xmlSchemaValidateSimpleTypeValue, the spec wants
15941 * a specific complex type error to be reported
15942 * additionally.
15943 */
15944 xmlSchemaVComplexTypeErr(ctxt,
15945 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015946 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015947 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015948 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15949 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015950 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015951 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015952 "Element '%s': Error while validating character "
15953 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015954 elem->name, type->name);
15955 if (value != NULL)
15956 xmlFree(value);
15957 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015958 return (-1);
15959 }
William M. Brack2f2a6632004-08-20 23:09:47 +000015960 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015961 if (ret == 0) {
15962 /*
15963 * Apply facets of the complexType. Be sure to pass the
15964 * built-in type to xmlSchemaValidateFacetsInternal.
15965 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015966 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000015967 * are used, or if the facets, defined by this complex type,
15968 * are to be used only. This here applies both facet sets.
15969 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015970
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015971 ret = xmlSchemaValidateFacetsInternal(ctxt,
15972 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015973 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015974 xmlSchemaVComplexTypeErr(ctxt,
15975 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015976 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015977 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015978 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15979 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015980 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015981 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015982 "Element '%s': Error while validating character "
15983 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000015984 "apply facets.\n",
15985 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015986 if (value != NULL)
15987 xmlFree(value);
15988 ctxt->type = oldtype;
15989 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015990 }
15991 }
15992 if (value != NULL)
15993 xmlFree(value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015994
Daniel Veillard01fa6152004-06-29 17:04:39 +000015995 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015996 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015997 default:
15998 TODO xmlGenericError(xmlGenericErrorContext,
15999 "unimplemented content type %d\n",
16000 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016001 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016002 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016003 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016004}
16005
16006/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016007 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016008 * @ctxt: a schema validation context
16009 * @elem: an element
16010 * @type: the list of type declarations
16011 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016012 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016013 *
16014 * Returns 0 if the element is schemas valid, a positive error code
16015 * number otherwise and -1 in case of internal or API error.
16016 */
16017static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016018xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016019 xmlSchemaTypePtr type,
16020 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016021{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016022 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016023
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016024
16025 if ((ctxt == NULL) || (type == NULL)) {
16026 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16027 "Internal error: xmlSchemaValidateElementByType, "
16028 "bad arguments", NULL);
16029 return (-1);
16030 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016031 /*
16032 * This one is called by "xmlSchemaValidateElementByDeclaration".
16033 * It will forward to the proper validation
16034 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016035 */
16036 if (type == NULL) {
16037 xmlSchemaVComplexTypeErr(ctxt,
16038 XML_SCHEMAV_CVC_TYPE_1,
16039 ctxt->node, NULL,
16040 "The type definition is absent");
16041 return (XML_SCHEMAV_CVC_TYPE_1);
16042 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016043
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016044 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
16045 xmlSchemaVComplexTypeErr(ctxt,
16046 XML_SCHEMAV_CVC_TYPE_2,
16047 ctxt->node, type,
16048 "The type definition is abstract");
16049 return (XML_SCHEMAV_CVC_TYPE_2);
16050 }
16051
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016052 switch (type->type) {
16053 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016054 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16055 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016056 break;
16057 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016058 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16059 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016060 break;
16061 case XML_SCHEMA_TYPE_BASIC:
16062 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16063 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16064 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016065 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16066 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016067 break;
16068 default:
16069 ret = -1;
16070 break;
16071 }
16072 if (ret == -1)
16073 return (-1);
16074 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016075 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016076}
16077
16078
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016079static int
16080xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16081 xmlSchemaAttributePtr decl,
16082 xmlSchemaAttrStatePtr state,
16083 xmlAttrPtr attr)
16084{
16085 xmlChar *value;
16086 const xmlChar *defValue;
16087 xmlSchemaValPtr defVal;
16088 int fixed;
16089 int ret;
16090
16091 if (decl->subtypes == NULL) {
16092 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16093 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16094 }
16095 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16096 ctxt->node = (xmlNodePtr) attr;
16097 ctxt->cur = attr->children;
16098 /*
16099 * NOTE: This call also checks the content nodes for correct type.
16100 */
16101 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16102 value, 1, 1, 1, 1);
16103
16104 /*
16105 * Handle 'fixed' attributes.
16106 */
16107 if (ret > 0) {
16108 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16109 /*
16110 * NOTE: Fixed value constraints will be not
16111 * applied if the value was invalid, because:
16112 * 1. The validation process does not return a precomputed
16113 * value.
16114 * 2. An invalid value implies a violation of a fixed
16115 * value constraint.
16116 */
16117 } else if (ret == 0) {
16118 state->state = XML_SCHEMAS_ATTR_CHECKED;
16119 if (xmlSchemaGetEffectiveValueConstraint(decl,
16120 &fixed, &defValue, &defVal) && (fixed == 1)) {
16121 /*
16122 * cvc-au : Attribute Locally Valid (Use)
16123 * For an attribute information item to be·valid·
16124 * with respect to an attribute use its ·normalized
16125 * value· must match the canonical lexical representation
16126 * of the attribute use's {value constraint} value, if it
16127 * is present and fixed.
16128 */
16129 /*
16130 * NOTE: the validation context holds in ctxt->value the
16131 * precomputed value of the attribute; well for some types,
16132 * fallback to string comparison if no computed value
16133 * exists.
16134 */
16135 if (((ctxt->value != NULL) &&
16136 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16137 ((ctxt->value == NULL) &&
16138 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16139 state->state =
16140 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16141 }
16142 }
16143 }
16144 if (value != NULL) {
16145 xmlFree(value);
16146 }
16147 return (ret);
16148}
16149
Daniel Veillard4255d502002-04-16 15:50:10 +000016150/**
16151 * xmlSchemaValidateAttributes:
16152 * @ctxt: a schema validation context
16153 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016154 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016155 *
16156 * Validate the attributes of an element.
16157 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016158 * 1. Existent, invalid attributes are reported in the form
16159 * "prefix:localName".
16160 * Reason: readability - it is easier to find the actual XML
16161 * representation of the attributes QName.
16162 * 2. Missing attributes are reported in the form
16163 * {"URI", "localName"}.
16164 * This is necessary, since the the prefix need not to be declared
16165 * at all, and thus is not computable.
16166 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016167 * Returns 0 if the element is schemas valid, a positive error code
16168 * number otherwise and -1 in case of internal or API error.
16169 */
16170static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016171xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016172{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016173 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016174 int ret;
16175 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016176 const xmlChar *defValue;
16177 xmlSchemaValPtr defVal;
16178 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016179 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016180 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016181 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016182 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016183 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016184 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016185#ifdef DEBUG_ATTR_VALIDATION
16186 int redundant = 0;
16187#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016188
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016189
Daniel Veillardc0826a72004-08-10 14:17:33 +000016190 /*
16191 * Allow all attributes if the type is anyType.
16192 */
16193 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16194 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016195
16196 oldnode = ctxt->node;
16197 if (type != NULL)
16198 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016199 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016200 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016201 attrDecl = attrUse->attr;
16202#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016203 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016204 printf("attr use - use: %d\n", attrDecl->occurs);
16205#endif
16206 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16207
16208 if (curState->decl == attrUse->attr) {
16209#ifdef DEBUG_ATTR_VALIDATION
16210 redundant = 1;
16211#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016212 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016213 attr = curState->attr;
16214#ifdef DEBUG_ATTR_VALIDATION
16215 printf("attr - name: %s\n", attr->name);
16216 if (attr->ns != NULL)
16217 printf("attr - ns: %s\n", attr->ns->href);
16218 else
16219 printf("attr - ns: none\n");
16220#endif
16221 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016222 if (attr == NULL)
16223 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016224 if (attrDecl->ref != NULL) {
16225 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016226 continue;
16227 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016228 if ((attrDecl->refNs == NULL) ||
16229 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016230 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016231 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016232 continue;
16233 }
16234 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016235 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016236 continue;
16237 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016238 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016239 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016240 if (attr->ns == NULL) {
16241 /*
William M. Bracke7091952004-05-11 15:09:58 +000016242 * accept an unqualified attribute only if the target
16243 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016244 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016245 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016246 /*
16247 * This check was removed, since the target namespace
16248 * was evaluated during parsing and already took
16249 * "attributeFormDefault" into account.
16250 */
16251 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016252 continue;
16253 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016254 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016255 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016256 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016257 attr->ns->href))
16258 continue;
16259 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016260 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016261#ifdef DEBUG_ATTR_VALIDATION
16262 printf("found\n");
16263#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016264 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016265 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016266 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016267 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016268 if (!found) {
16269 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16270 xmlSchemaAttrStatePtr tmp;
16271
Daniel Veillard3646d642004-06-02 19:19:14 +000016272#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016273 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016274#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016275 /*
16276 * Add a new dummy attribute state.
16277 */
16278 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16279 if (tmp == NULL) {
16280 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16281 ctxt->node = oldnode;
16282 return (-1);
16283 }
16284 tmp->attr = NULL;
16285 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16286 tmp->decl = attrDecl;
16287 tmp->next = NULL;
16288
16289 if (reqAttrStates == NULL) {
16290 reqAttrStates = tmp;
16291 reqAttrStatesTop = tmp;
16292 } else {
16293 reqAttrStatesTop->next = tmp;
16294 reqAttrStatesTop = tmp;
16295 }
16296 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16297 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16298 &fixed, &defValue, &defVal))) {
16299 xmlSchemaAttrStatePtr tmp;
16300 /*
16301 * Handle non existent default/fixed attributes.
16302 */
16303 tmp = (xmlSchemaAttrStatePtr)
16304 xmlMalloc(sizeof(xmlSchemaAttrState));
16305 if (tmp == NULL) {
16306 xmlSchemaVErrMemory(ctxt,
16307 "registering schema specified attributes", NULL);
16308 ctxt->node = oldnode;
16309 return (-1);
16310 }
16311 tmp->attr = NULL;
16312 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16313 tmp->decl = attrDecl;
16314 tmp->value = defValue;
16315 tmp->next = NULL;
16316
16317 if (defAttrStates == NULL) {
16318 defAttrStates = tmp;
16319 defAttrStates = tmp;
16320 } else {
16321 defAttrStates->next = tmp;
16322 defAttrStatesTop = tmp;
16323 }
16324 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016325 }
16326 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016327 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016328 /*
16329 * Add required attributes to the attribute states of the context.
16330 */
16331 if (reqAttrStates != NULL) {
16332 if (ctxt->attr == NULL) {
16333 ctxt->attr = reqAttrStates;
16334 } else {
16335 ctxt->attrTop->next = reqAttrStates;
16336 }
16337 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016338 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016339 /*
16340 * Process wildcards.
16341 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016342
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016343 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016344#ifdef DEBUG_ATTR_VALIDATION
16345 xmlSchemaWildcardNsPtr ns;
16346 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016347 if (type->attributeWildcard->processContents ==
16348 XML_SCHEMAS_ANY_LAX)
16349 printf("processContents: lax\n");
16350 else if (type->attributeWildcard->processContents ==
16351 XML_SCHEMAS_ANY_STRICT)
16352 printf("processContents: strict\n");
16353 else
16354 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016355 if (type->attributeWildcard->any)
16356 printf("type: any\n");
16357 else if (type->attributeWildcard->negNsSet != NULL) {
16358 printf("type: negated\n");
16359 if (type->attributeWildcard->negNsSet->value == NULL)
16360 printf("ns: (absent)\n");
16361 else
16362 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16363 } else if (type->attributeWildcard->nsSet != NULL) {
16364 printf("type: set\n");
16365 ns = type->attributeWildcard->nsSet;
16366 while (ns != NULL) {
16367 if (ns->value == NULL)
16368 printf("ns: (absent)\n");
16369 else
16370 printf("ns: %s\n", ns->value);
16371 ns = ns->next;
16372 }
16373 } else
16374 printf("empty\n");
16375
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016376
16377#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016378 curState = ctxt->attr;
16379 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016380 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16381 if (curState->attr->ns != NULL)
16382 nsURI = curState->attr->ns->href;
16383 else
16384 nsURI = NULL;
16385 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16386 nsURI)) {
16387 /*
16388 * Handle processContents.
16389 */
16390 if ((type->attributeWildcard->processContents ==
16391 XML_SCHEMAS_ANY_LAX) ||
16392 (type->attributeWildcard->processContents ==
16393 XML_SCHEMAS_ANY_STRICT)) {
16394
16395 attr = curState->attr;
16396 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016397 attr->name, nsURI);
16398 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016399 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016400 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016401 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016402 } else if (type->attributeWildcard->processContents ==
16403 XML_SCHEMAS_ANY_LAX) {
16404 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16405 }
16406 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016407 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016408 }
16409 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016410 curState = curState->next;
16411 }
16412 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016413
Daniel Veillardc0826a72004-08-10 14:17:33 +000016414 /*
16415 * Report missing and illegal attributes.
16416 */
16417 if (ctxt->attr != NULL) {
16418 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016419 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016420 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16421 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016422 if (curState->decl != NULL) {
16423 if (curState->decl->ref != NULL)
16424 attrDecl = curState->decl->refDecl;
16425 else
16426 attrDecl = curState->decl;
16427 } else
16428 attrDecl = NULL;
16429 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16430 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16431 } else if (curState->state ==
16432 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16433 xmlSchemaVCustomErr(ctxt,
16434 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16435 (xmlNodePtr) attr,
16436 (xmlSchemaTypePtr) attrDecl,
16437 "The type definition is absent",
16438 NULL);
16439 } else if (curState->state ==
16440 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16441 xmlSchemaVCustomErr(ctxt,
16442 XML_SCHEMAV_CVC_AU,
16443 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16444 "The value does not match the fixed value "
16445 "constraint", NULL);
16446 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016447 /* TODO: "prohibited" won't ever be touched here!.
16448 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16449 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016450 /*
16451 * TODO: One might report different error messages
16452 * for the following errors.
16453 */
16454 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016455 xmlSchemaVIllegalAttrErr(ctxt,
16456 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16457 } else {
16458 xmlSchemaVIllegalAttrErr(ctxt,
16459 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16460 }
16461 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016462 }
16463 curState = curState->next;
16464 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016465 }
16466
16467 /*
16468 * Add missing default/fixed attributes.
16469 */
16470 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16471 curState = defAttrStates;
16472 while (curState != NULL) {
16473 attrDecl = curState->decl;
16474 if (attrDecl->ref != NULL)
16475 attrDecl = attrDecl->refDecl;
16476 /*
16477 * PSVI: Add a new attribute node to the current element.
16478 */
16479 if (attrDecl->targetNamespace == NULL) {
16480 xmlNewProp(elem, attrDecl->name, curState->value);
16481 } else {
16482 xmlNsPtr ns;
16483
16484 ns = xmlSearchNsByHref(elem->doc, elem,
16485 attrDecl->targetNamespace);
16486 if (ns == NULL) {
16487 xmlChar prefix[12];
16488 int counter = 1;
16489
16490 attr = curState->attr;
16491 /*
16492 * Create a namespace declaration on the validation
16493 * root node if no namespace declaration is in scope.
16494 */
16495 snprintf((char *) prefix, sizeof(prefix), "p");
16496 /*
16497 * This is somehow not performant, since the ancestor
16498 * axis beyond @elem will be searched as well.
16499 */
16500 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16501 while (ns != NULL) {
16502 if (counter > 1000) {
16503 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16504 XML_SCHEMAV_INTERNAL,
16505 "Internal error: xmlSchemaValidateAttributes, "
16506 "could not compute a ns prefix for "
16507 "default/fixed attribute '%s'.\n",
16508 attrDecl->name, NULL);
16509
16510 break;
16511 }
16512 snprintf((char *) prefix,
16513 sizeof(prefix), "p%d", counter++);
16514 ns = xmlSearchNs(elem->doc, elem,
16515 BAD_CAST prefix);
16516 }
16517 if (ns == NULL) {
16518 ns = xmlNewNs(ctxt->validationRoot,
16519 attrDecl->targetNamespace, BAD_CAST prefix);
16520 xmlNewNsProp(elem, ns, attrDecl->name,
16521 curState->value);
16522 }
16523 } else {
16524 xmlNewNsProp(elem, ns, attrDecl->name,
16525 curState->value);
16526 }
16527 }
16528 curState = curState->next;
16529 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016530 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016531 if (defAttrStates != NULL)
16532 xmlSchemaFreeAttributeStates(defAttrStates);
16533
Daniel Veillard3646d642004-06-02 19:19:14 +000016534#ifdef DEBUG_ATTR_VALIDATION
16535 if (redundant)
16536 xmlGenericError(xmlGenericErrorContext,
16537 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16538 type->name);
16539#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016540 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016541 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016542}
16543
16544/**
16545 * xmlSchemaValidateElement:
16546 * @ctxt: a schema validation context
16547 * @elem: an element
16548 *
16549 * Validate an element in a tree
16550 *
16551 * Returns 0 if the element is schemas valid, a positive error code
16552 * number otherwise and -1 in case of internal or API error.
16553 */
16554static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016555xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016556{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016557 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016558 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016559
Daniel Veillardc0826a72004-08-10 14:17:33 +000016560 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016561 * This one is called by xmlSchemaValidateDocument and
16562 * xmlSchemaValidateOneElement.
16563 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016564 if (ctxt->schema == NULL) {
16565 /*
16566 * No schema was specified at time of creation of the validation
16567 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16568 * of the instance to build a schema.
16569 */
16570 if (ctxt->pctxt == NULL)
16571 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16572 if (ctxt->pctxt == NULL)
16573 return (-1);
16574 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16575 if (ctxt->schema == NULL)
16576 return (-1);
16577 /* TODO: assign user data. */
16578 ctxt->pctxt->error = ctxt->error;
16579 ctxt->pctxt->warning = ctxt->warning;
16580 ctxt->xsiAssemble = 1;
16581 } else
16582 ctxt->xsiAssemble = 0;
16583 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16584 * ctxt->xsiAssemble = 1;
16585 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016586 /*
16587 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016588 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016589 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016590 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16591 if (ret == -1) {
16592 xmlSchemaVCustomErr(ctxt,
16593 XML_SCHEMAV_INTERNAL,
16594 ctxt->node, NULL,
16595 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016596 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016597 }
16598 /*
16599 * NOTE: We won't react on schema parser errors here.
16600 * TODO: But a warning would be nice.
16601 */
16602 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016603 if (ret != -1) {
16604 if (ctxt->node->ns != NULL)
16605 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16606 ctxt->node->ns->href);
16607 else
16608 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16609
16610 if (elemDecl == NULL) {
16611 xmlSchemaVCustomErr(ctxt,
16612 XML_SCHEMAV_CVC_ELT_1,
16613 ctxt->node, NULL,
16614 "No matching global declaration available", NULL);
16615 ret = XML_SCHEMAV_CVC_ELT_1;
16616 } else {
16617 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16618 if (ret < 0) {
16619 xmlSchemaVCustomErr(ctxt,
16620 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16621 "Internal error: xmlSchemaValidateElement, "
16622 "calling validation by declaration", NULL);
16623 }
16624 }
16625 }
16626 /* ctxt->xsiAssemble = 0; */
16627 if (ctxt->xsiAssemble) {
16628 if (ctxt->schema != NULL) {
16629 xmlSchemaFree(ctxt->schema);
16630 ctxt->schema = NULL;
16631 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016632 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016633 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016634}
16635
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016636
Daniel Veillard4255d502002-04-16 15:50:10 +000016637/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016638 * xmlSchemaValidateOneElement:
16639 * @ctxt: a schema validation context
16640 * @elem: an element node
16641 *
16642 * Validate a branch of a tree, starting with the given @elem.
16643 *
16644 * Returns 0 if the element and its subtree is valid, a positive error
16645 * code number otherwise and -1 in case of an internal or API error.
16646 */
16647int
16648xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16649{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016650 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016651 return (-1);
16652
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016653 if (ctxt->schema == NULL) {
16654 xmlSchemaVErr(ctxt, NULL,
16655 XML_SCHEMAV_INTERNAL,
16656 "API error: xmlSchemaValidateOneElement, "
16657 "no schema specified.\n", NULL, NULL);
16658 return (-1);
16659 }
16660
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016661 ctxt->doc = elem->doc;
16662 ctxt->err = 0;
16663 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016664 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016665 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016666 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016667}
16668
16669/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016670 * xmlSchemaValidateDocument:
16671 * @ctxt: a schema validation context
16672 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016673 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016674 *
16675 * Validate a document tree in memory.
16676 *
16677 * Returns 0 if the document is schemas valid, a positive error code
16678 * number otherwise and -1 in case of internal or API error.
16679 */
16680static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016681xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16682{
Daniel Veillard4255d502002-04-16 15:50:10 +000016683 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016684
Daniel Veillard4255d502002-04-16 15:50:10 +000016685 root = xmlDocGetRootElement(doc);
16686 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016687 xmlSchemaVCustomErr(ctxt,
16688 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16689 (xmlNodePtr) doc, NULL,
16690 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016691 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016692 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016693 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016694 /*
16695 * Okay, start the recursive validation
16696 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016697 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016698 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016699 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016700
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016701 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016702}
16703
16704/************************************************************************
16705 * *
16706 * SAX Validation code *
16707 * *
16708 ************************************************************************/
16709
16710/************************************************************************
16711 * *
16712 * Validation interfaces *
16713 * *
16714 ************************************************************************/
16715
16716/**
16717 * xmlSchemaNewValidCtxt:
16718 * @schema: a precompiled XML Schemas
16719 *
16720 * Create an XML Schemas validation context based on the given schema
16721 *
16722 * Returns the validation context or NULL in case of error
16723 */
16724xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016725xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16726{
Daniel Veillard4255d502002-04-16 15:50:10 +000016727 xmlSchemaValidCtxtPtr ret;
16728
16729 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16730 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016731 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016732 return (NULL);
16733 }
16734 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016735 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016736 ret->attrTop = NULL;
16737 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016738 return (ret);
16739}
16740
16741/**
16742 * xmlSchemaFreeValidCtxt:
16743 * @ctxt: the schema validation context
16744 *
16745 * Free the resources associated to the schema validation context
16746 */
16747void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016748xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16749{
Daniel Veillard4255d502002-04-16 15:50:10 +000016750 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016751 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016752 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016753 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016754 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016755 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016756 if (ctxt->pctxt != NULL) {
16757 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16758 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016759 xmlFree(ctxt);
16760}
16761
16762/**
16763 * xmlSchemaSetValidErrors:
16764 * @ctxt: a schema validation context
16765 * @err: the error function
16766 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016767 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016768 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016769 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016770 */
16771void
16772xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016773 xmlSchemaValidityErrorFunc err,
16774 xmlSchemaValidityWarningFunc warn, void *ctx)
16775{
Daniel Veillard4255d502002-04-16 15:50:10 +000016776 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016777 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016778 ctxt->error = err;
16779 ctxt->warning = warn;
16780 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016781 if (ctxt->pctxt != NULL)
16782 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000016783}
16784
16785/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016786 * xmlSchemaGetValidErrors:
16787 * @ctxt: a XML-Schema validation context
16788 * @err: the error function result
16789 * @warn: the warning function result
16790 * @ctx: the functions context result
16791 *
16792 * Get the error and warning callback informations
16793 *
16794 * Returns -1 in case of error and 0 otherwise
16795 */
16796int
16797xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
16798 xmlSchemaValidityErrorFunc * err,
16799 xmlSchemaValidityWarningFunc * warn, void **ctx)
16800{
16801 if (ctxt == NULL)
16802 return (-1);
16803 if (err != NULL)
16804 *err = ctxt->error;
16805 if (warn != NULL)
16806 *warn = ctxt->warning;
16807 if (ctx != NULL)
16808 *ctx = ctxt->userData;
16809 return (0);
16810}
16811
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016812
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016813/**
16814 * xmlSchemaValidCtxtSetOptions:
16815 * @ctxt: a schema validation context
16816 * @options: a combination of xmlSchemaValidOption
16817 *
16818 * Sets the options to be used during the validation.
16819 *
16820 * Returns 0 in case of success, -1 in case of an
16821 * API error.
16822 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016823int
16824xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
16825 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016826
16827{
16828 int i;
16829
16830 if (ctxt == NULL)
16831 return (-1);
16832 /*
16833 * WARNING: Change the start value if adding to the
16834 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016835 * TODO: Is there an other, more easy to maintain,
16836 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016837 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016838 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016839 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016840 xmlSchemaVErr(ctxt, NULL,
16841 XML_SCHEMAV_INTERNAL,
16842 "Internal error: xmlSchemaSetValidOptions, "
16843 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016844 return (-1);
16845 }
16846 }
16847 ctxt->options = options;
16848 return (0);
16849}
16850
16851/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016852 * xmlSchemaGetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016853 * @ctxt: a schema validation context
16854 *
16855 * Returns the option combination of the validation context.
16856 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016857int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016858xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
16859
16860{
16861 if (ctxt == NULL)
16862 return (-1);
16863 else
16864 return (ctxt->options);
16865}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016866
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016867
Daniel Veillard259f0df2004-08-18 09:13:18 +000016868/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016869 * xmlSchemaValidateDoc:
16870 * @ctxt: a schema validation context
16871 * @doc: a parsed document tree
16872 *
16873 * Validate a document tree in memory.
16874 *
16875 * Returns 0 if the document is schemas valid, a positive error code
16876 * number otherwise and -1 in case of internal or API error.
16877 */
16878int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016879xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16880{
Daniel Veillard4255d502002-04-16 15:50:10 +000016881 int ret;
16882
16883 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016884 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016885
16886 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000016887 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016888 ctxt->nberrors = 0;
16889
16890 /*
16891 if (ctxt->schema == NULL) {
16892 xmlSchemaVErr(ctxt, NULL,
16893 XML_SCHEMAV_INTERNAL,
16894 "API error: xmlSchemaValidateDoc, "
16895 "no schema specified and assembling of schemata "
16896 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
16897 "is not enabled.\n", NULL, NULL);
16898 return (-1);
16899 }
16900 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016901 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016902 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016903}
16904
16905/**
16906 * xmlSchemaValidateStream:
16907 * @ctxt: a schema validation context
16908 * @input: the input to use for reading the data
16909 * @enc: an optional encoding information
16910 * @sax: a SAX handler for the resulting events
16911 * @user_data: the context to provide to the SAX handler.
16912 *
16913 * Validate a document tree in memory.
16914 *
16915 * Returns 0 if the document is schemas valid, a positive error code
16916 * number otherwise and -1 in case of internal or API error.
16917 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016918int
Daniel Veillard4255d502002-04-16 15:50:10 +000016919xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016920 xmlParserInputBufferPtr input, xmlCharEncoding enc,
16921 xmlSAXHandlerPtr sax, void *user_data)
16922{
Daniel Veillard4255d502002-04-16 15:50:10 +000016923 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016924 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016925 ctxt->input = input;
16926 ctxt->enc = enc;
16927 ctxt->sax = sax;
16928 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016929 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000016930}
16931
16932#endif /* LIBXML_SCHEMAS_ENABLED */