blob: f6bc63d47ad3255f238544e7b0a7c1fe0ef97a14 [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.
15 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016#define IN_LIBXML
17#include "libxml.h"
18
19#ifdef LIBXML_SCHEMAS_ENABLED
20
21#include <string.h>
22#include <libxml/xmlmemory.h>
23#include <libxml/parser.h>
24#include <libxml/parserInternals.h>
25#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000026#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000027
28#include <libxml/xmlschemas.h>
29#include <libxml/schemasInternals.h>
30#include <libxml/xmlschemastypes.h>
31#include <libxml/xmlautomata.h>
32#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000033#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000034
Daniel Veillarda84c0b32003-06-02 16:58:46 +000035/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000036
Daniel Veillard82bbbd42003-05-11 20:16:09 +000037/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000038
Daniel Veillard82bbbd42003-05-11 20:16:09 +000039/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000040
Daniel Veillard118aed72002-09-24 14:13:13 +000041/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000042
Daniel Veillard4255d502002-04-16 15:50:10 +000043/* #define DEBUG_AUTOMATA 1 */
44
45#define UNBOUNDED (1 << 30)
46#define TODO \
47 xmlGenericError(xmlGenericErrorContext, \
48 "Unimplemented block at %s:%d\n", \
49 __FILE__, __LINE__);
50
Daniel Veillard5a872412002-05-22 06:40:27 +000051#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053/*
54 * The XML Schemas namespaces
55 */
56static const xmlChar *xmlSchemaNs = (const xmlChar *)
57 "http://www.w3.org/2001/XMLSchema";
58
59static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
60 "http://www.w3.org/2001/XMLSchema-instance";
61
62#define IS_SCHEMA(node, type) \
63 ((node != NULL) && (node->ns != NULL) && \
64 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
65 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
66
67#define XML_SCHEMAS_PARSE_ERROR 1
68
Daniel Veillardbd2904b2003-11-25 15:38:59 +000069#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
70
Daniel Veillard4255d502002-04-16 15:50:10 +000071struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000072 void *userData; /* user specific data block */
73 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
74 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000075 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000077 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000078
Daniel Veillardbe9c6322003-11-22 20:37:51 +000079 xmlSchemaPtr topschema; /* The main schema */
80 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
81
Daniel Veillardd0c9c322003-10-10 00:49:42 +000082 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000083 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000084 int counter;
85
Daniel Veillardbe9c6322003-11-22 20:37:51 +000086 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000087 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000088 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +000089
Daniel Veillardd0c9c322003-10-10 00:49:42 +000090 const char *buffer;
91 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000092
Daniel Veillard4255d502002-04-16 15:50:10 +000093 /*
94 * Used to build complex element content models
95 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000096 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000097 xmlAutomataStatePtr start;
98 xmlAutomataStatePtr end;
99 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000100
101 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000102 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard4255d502002-04-16 15:50:10 +0000103};
104
105
106#define XML_SCHEMAS_ATTR_UNKNOWN 1
107#define XML_SCHEMAS_ATTR_CHECKED 2
108
109typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
110typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
111struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000112 xmlAttrPtr attr;
113 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +0000114};
115
116/**
117 * xmlSchemaValidCtxt:
118 *
119 * A Schemas validation context
120 */
121
122struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 void *userData; /* user specific data block */
124 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
125 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000126 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000127
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000128 xmlSchemaPtr schema; /* The schema in use */
129 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000130 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000131 xmlCharEncoding enc;
132 xmlSAXHandlerPtr sax;
133 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000134
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000135 xmlDocPtr myDoc;
136 int err;
137 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000138
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000139 xmlNodePtr node;
140 xmlNodePtr cur;
141 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000142
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000143 xmlRegExecCtxtPtr regexp;
144 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000145
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000146 int attrNr;
147 int attrBase;
148 int attrMax;
149 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000150};
151
Daniel Veillard1d913862003-11-21 00:28:39 +0000152/*
153 * These are the entries in the schemas importSchemas hash table
154 */
155typedef struct _xmlSchemaImport xmlSchemaImport;
156typedef xmlSchemaImport *xmlSchemaImportPtr;
157struct _xmlSchemaImport {
158 const xmlChar *schemaLocation;
159 xmlSchemaPtr schema;
160};
Daniel Veillard4255d502002-04-16 15:50:10 +0000161
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000162/*
163 * These are the entries associated to includes in a schemas
164 */
165typedef struct _xmlSchemaInclude xmlSchemaInclude;
166typedef xmlSchemaInclude *xmlSchemaIncludePtr;
167struct _xmlSchemaInclude {
168 xmlSchemaIncludePtr next;
169
170 const xmlChar *schemaLocation;
171 xmlDocPtr doc;
172};
173
Daniel Veillard4255d502002-04-16 15:50:10 +0000174/************************************************************************
175 * *
176 * Some predeclarations *
177 * *
178 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
180 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000181 const xmlChar * value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000182
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000183static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
184 xmlSchemaPtr schema,
185 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000186static int
187xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
188 xmlSchemaTypePtr type,
189 const xmlChar * value,
190 int fireErrors);
191
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000192/************************************************************************
193 * *
194 * Datatype error handlers *
195 * *
196 ************************************************************************/
197
198/**
199 * xmlSchemaPErrMemory:
200 * @node: a context node
201 * @extra: extra informations
202 *
203 * Handle an out of memory condition
204 */
205static void
206xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
207 const char *extra, xmlNodePtr node)
208{
209 if (ctxt != NULL)
210 ctxt->nberrors++;
211 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
212 extra);
213}
214
215/**
216 * xmlSchemaPErr:
217 * @ctxt: the parsing context
218 * @node: the context node
219 * @error: the error code
220 * @msg: the error message
221 * @str1: extra data
222 * @str2: extra data
223 *
224 * Handle a parser error
225 */
226static void
227xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
228 const char *msg, const xmlChar * str1, const xmlChar * str2)
229{
230 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000231 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000232 void *data = NULL;
233
234 if (ctxt != NULL) {
235 ctxt->nberrors++;
236 channel = ctxt->error;
237 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000238 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000239 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000240 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000241 error, XML_ERR_ERROR, NULL, 0,
242 (const char *) str1, (const char *) str2, NULL, 0, 0,
243 msg, str1, str2);
244}
245
246/**
247 * xmlSchemaPErr2:
248 * @ctxt: the parsing context
249 * @node: the context node
250 * @node: the current child
251 * @error: the error code
252 * @msg: the error message
253 * @str1: extra data
254 * @str2: extra data
255 *
256 * Handle a parser error
257 */
258static void
259xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
260 xmlNodePtr child, int error,
261 const char *msg, const xmlChar * str1, const xmlChar * str2)
262{
263 if (child != NULL)
264 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
265 else
266 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
267}
268
269/**
270 * xmlSchemaVTypeErrMemory:
271 * @node: a context node
272 * @extra: extra informations
273 *
274 * Handle an out of memory condition
275 */
276static void
277xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
278 const char *extra, xmlNodePtr node)
279{
280 if (ctxt != NULL) {
281 ctxt->nberrors++;
282 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
283 }
284 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
285 extra);
286}
287
288/**
289 * xmlSchemaVErr3:
290 * @ctxt: the validation context
291 * @node: the context node
292 * @error: the error code
293 * @msg: the error message
294 * @str1: extra data
295 * @str2: extra data
296 * @str3: extra data
297 *
298 * Handle a validation error
299 */
300static void
301xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
302 const char *msg, const xmlChar *str1, const xmlChar *str2,
303 const xmlChar *str3)
304{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000305 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000306 xmlGenericErrorFunc channel = NULL;
307 void *data = NULL;
308
309 if (ctxt != NULL) {
310 ctxt->nberrors++;
311 ctxt->err = error;
312 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000313 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000314 data = ctxt->userData;
315 }
316 /* reajust to global error numbers */
317 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000318 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000319 error, XML_ERR_ERROR, NULL, 0,
320 (const char *) str1, (const char *) str2,
321 (const char *) str3, 0, 0,
322 msg, str1, str2, str3);
323}
324/**
325 * xmlSchemaVErr:
326 * @ctxt: the validation context
327 * @node: the context node
328 * @error: the error code
329 * @msg: the error message
330 * @str1: extra data
331 * @str2: extra data
332 *
333 * Handle a validation error
334 */
335static void
336xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
337 const char *msg, const xmlChar * str1, const xmlChar * str2)
338{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000339 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000340 xmlGenericErrorFunc channel = NULL;
341 void *data = NULL;
342
343 if (ctxt != NULL) {
344 ctxt->nberrors++;
345 ctxt->err = error;
346 channel = ctxt->error;
347 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000348 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000349 }
350 /* reajust to global error numbers */
351 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000352 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000353 error, XML_ERR_ERROR, NULL, 0,
354 (const char *) str1, (const char *) str2, NULL, 0, 0,
355 msg, str1, str2);
356}
Daniel Veillard4255d502002-04-16 15:50:10 +0000357
358/************************************************************************
359 * *
360 * Allocation functions *
361 * *
362 ************************************************************************/
363
364/**
365 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000366 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000367 *
368 * Allocate a new Schema structure.
369 *
370 * Returns the newly allocated structure or NULL in case or error
371 */
372static xmlSchemaPtr
373xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
374{
375 xmlSchemaPtr ret;
376
377 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
378 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000379 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000380 return (NULL);
381 }
382 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000383 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000384 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000385
386 return (ret);
387}
388
389/**
390 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000391 *
392 * Allocate a new Facet structure.
393 *
394 * Returns the newly allocated structure or NULL in case or error
395 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000396xmlSchemaFacetPtr
397xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000398{
399 xmlSchemaFacetPtr ret;
400
401 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
402 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000403 return (NULL);
404 }
405 memset(ret, 0, sizeof(xmlSchemaFacet));
406
407 return (ret);
408}
409
410/**
411 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000412 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000413 * @node: a node
414 *
415 * Allocate a new annotation structure.
416 *
417 * Returns the newly allocated structure or NULL in case or error
418 */
419static xmlSchemaAnnotPtr
420xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
421{
422 xmlSchemaAnnotPtr ret;
423
424 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
425 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000426 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000427 return (NULL);
428 }
429 memset(ret, 0, sizeof(xmlSchemaAnnot));
430 ret->content = node;
431 return (ret);
432}
433
434/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000435 * xmlSchemaFreeAnnot:
436 * @annot: a schema type structure
437 *
438 * Deallocate a annotation structure
439 */
440static void
441xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
442{
443 if (annot == NULL)
444 return;
445 xmlFree(annot);
446}
447
448/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000449 * xmlSchemaFreeImport:
450 * @import: a schema import structure
451 *
452 * Deallocate an import structure
453 */
454static void
455xmlSchemaFreeImport(xmlSchemaImportPtr import)
456{
457 if (import == NULL)
458 return;
459
460 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000461 xmlFree(import);
462}
463
464/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000465 * xmlSchemaFreeInclude:
466 * @include: a schema include structure
467 *
468 * Deallocate an include structure
469 */
470static void
471xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
472{
473 if (include == NULL)
474 return;
475
476 xmlFreeDoc(include->doc);
477 xmlFree(include);
478}
479
480/**
481 * xmlSchemaFreeIncludeList:
482 * @includes: a schema include list
483 *
484 * Deallocate an include structure
485 */
486static void
487xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
488{
489 xmlSchemaIncludePtr next;
490
491 while (includes != NULL) {
492 next = includes->next;
493 xmlSchemaFreeInclude(includes);
494 includes = next;
495 }
496}
497
498/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000499 * xmlSchemaFreeNotation:
500 * @schema: a schema notation structure
501 *
502 * Deallocate a Schema Notation structure.
503 */
504static void
505xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
506{
507 if (nota == NULL)
508 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000509 xmlFree(nota);
510}
511
512/**
513 * xmlSchemaFreeAttribute:
514 * @schema: a schema attribute structure
515 *
516 * Deallocate a Schema Attribute structure.
517 */
518static void
519xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
520{
521 if (attr == NULL)
522 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000523 xmlFree(attr);
524}
525
526/**
527 * xmlSchemaFreeAttributeGroup:
528 * @schema: a schema attribute group structure
529 *
530 * Deallocate a Schema Attribute Group structure.
531 */
532static void
533xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
534{
535 if (attr == NULL)
536 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000537 xmlFree(attr);
538}
539
540/**
541 * xmlSchemaFreeElement:
542 * @schema: a schema element structure
543 *
544 * Deallocate a Schema Element structure.
545 */
546static void
547xmlSchemaFreeElement(xmlSchemaElementPtr elem)
548{
549 if (elem == NULL)
550 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000551 if (elem->annot != NULL)
552 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000553 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000554 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000555 xmlFree(elem);
556}
557
558/**
559 * xmlSchemaFreeFacet:
560 * @facet: a schema facet structure
561 *
562 * Deallocate a Schema Facet structure.
563 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000564void
Daniel Veillard4255d502002-04-16 15:50:10 +0000565xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
566{
567 if (facet == NULL)
568 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000569 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000570 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000571 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000573 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000574 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000575 xmlFree(facet);
576}
577
578/**
579 * xmlSchemaFreeType:
580 * @type: a schema type structure
581 *
582 * Deallocate a Schema Type structure.
583 */
584void
585xmlSchemaFreeType(xmlSchemaTypePtr type)
586{
587 if (type == NULL)
588 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000589 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000590 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000591 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000592 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000593
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000594 facet = type->facets;
595 while (facet != NULL) {
596 next = facet->next;
597 xmlSchemaFreeFacet(facet);
598 facet = next;
599 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000600 }
601 xmlFree(type);
602}
603
604/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000605 * xmlSchemaFreeTypeList:
606 * @type: a schema type structure
607 *
608 * Deallocate a Schema Type structure.
609 */
610static void
611xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
612{
613 xmlSchemaTypePtr next;
614
615 while (type != NULL) {
616 next = type->redef;
617 xmlSchemaFreeType(type);
618 type = next;
619 }
620}
621
622/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000623 * xmlSchemaFree:
624 * @schema: a schema structure
625 *
626 * Deallocate a Schema structure.
627 */
628void
629xmlSchemaFree(xmlSchemaPtr schema)
630{
631 if (schema == NULL)
632 return;
633
Daniel Veillard4255d502002-04-16 15:50:10 +0000634 if (schema->notaDecl != NULL)
635 xmlHashFree(schema->notaDecl,
636 (xmlHashDeallocator) xmlSchemaFreeNotation);
637 if (schema->attrDecl != NULL)
638 xmlHashFree(schema->attrDecl,
639 (xmlHashDeallocator) xmlSchemaFreeAttribute);
640 if (schema->attrgrpDecl != NULL)
641 xmlHashFree(schema->attrgrpDecl,
642 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
643 if (schema->elemDecl != NULL)
644 xmlHashFree(schema->elemDecl,
645 (xmlHashDeallocator) xmlSchemaFreeElement);
646 if (schema->typeDecl != NULL)
647 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000648 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000649 if (schema->groupDecl != NULL)
650 xmlHashFree(schema->groupDecl,
651 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000652 if (schema->schemasImports != NULL)
653 xmlHashFree(schema->schemasImports,
654 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000655 if (schema->includes != NULL) {
656 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
657 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000658 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000659 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000660 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000661 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000662 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000663
664 xmlFree(schema);
665}
666
667/************************************************************************
668 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000669 * Debug functions *
670 * *
671 ************************************************************************/
672
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000673#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000674
Daniel Veillard4255d502002-04-16 15:50:10 +0000675/**
676 * xmlSchemaElementDump:
677 * @elem: an element
678 * @output: the file output
679 *
680 * Dump the element
681 */
682static void
683xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000684 const xmlChar * name ATTRIBUTE_UNUSED,
685 const xmlChar * context ATTRIBUTE_UNUSED,
686 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000687{
688 if (elem == NULL)
689 return;
690
691 fprintf(output, "Element ");
692 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000693 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000694 fprintf(output, ": %s ", elem->name);
695 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000696 fprintf(output, "namespace '%s' ", namespace);
697
Daniel Veillard4255d502002-04-16 15:50:10 +0000698 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000699 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000700 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000701 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000702 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000703 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000704 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000706 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000707 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000708 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000709 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000710 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000711 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000712 fprintf(output, "\n");
713 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000714 fprintf(output, " ");
715 if (elem->minOccurs != 1)
716 fprintf(output, "min: %d ", elem->minOccurs);
717 if (elem->maxOccurs >= UNBOUNDED)
718 fprintf(output, "max: unbounded\n");
719 else if (elem->maxOccurs != 1)
720 fprintf(output, "max: %d\n", elem->maxOccurs);
721 else
722 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000723 }
724 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000725 fprintf(output, " type: %s", elem->namedType);
726 if (elem->namedTypeNs != NULL)
727 fprintf(output, " ns %s\n", elem->namedTypeNs);
728 else
729 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000730 }
731 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000732 fprintf(output, " substitutionGroup: %s", elem->substGroup);
733 if (elem->substGroupNs != NULL)
734 fprintf(output, " ns %s\n", elem->substGroupNs);
735 else
736 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000737 }
738 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000739 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000740}
741
742/**
743 * xmlSchemaAnnotDump:
744 * @output: the file output
745 * @annot: a annotation
746 *
747 * Dump the annotation
748 */
749static void
750xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
751{
752 xmlChar *content;
753
754 if (annot == NULL)
755 return;
756
757 content = xmlNodeGetContent(annot->content);
758 if (content != NULL) {
759 fprintf(output, " Annot: %s\n", content);
760 xmlFree(content);
761 } else
762 fprintf(output, " Annot: empty\n");
763}
764
765/**
766 * xmlSchemaTypeDump:
767 * @output: the file output
768 * @type: a type structure
769 *
770 * Dump a SchemaType structure
771 */
772static void
773xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
774{
775 if (type == NULL) {
776 fprintf(output, "Type: NULL\n");
777 return;
778 }
779 fprintf(output, "Type: ");
780 if (type->name != NULL)
781 fprintf(output, "%s, ", type->name);
782 else
783 fprintf(output, "no name");
784 switch (type->type) {
785 case XML_SCHEMA_TYPE_BASIC:
786 fprintf(output, "basic ");
787 break;
788 case XML_SCHEMA_TYPE_SIMPLE:
789 fprintf(output, "simple ");
790 break;
791 case XML_SCHEMA_TYPE_COMPLEX:
792 fprintf(output, "complex ");
793 break;
794 case XML_SCHEMA_TYPE_SEQUENCE:
795 fprintf(output, "sequence ");
796 break;
797 case XML_SCHEMA_TYPE_CHOICE:
798 fprintf(output, "choice ");
799 break;
800 case XML_SCHEMA_TYPE_ALL:
801 fprintf(output, "all ");
802 break;
803 case XML_SCHEMA_TYPE_UR:
804 fprintf(output, "ur ");
805 break;
806 case XML_SCHEMA_TYPE_RESTRICTION:
807 fprintf(output, "restriction ");
808 break;
809 case XML_SCHEMA_TYPE_EXTENSION:
810 fprintf(output, "extension ");
811 break;
812 default:
813 fprintf(output, "unknowntype%d ", type->type);
814 break;
815 }
816 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000817 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000818 }
819 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000820 case XML_SCHEMA_CONTENT_UNKNOWN:
821 fprintf(output, "unknown ");
822 break;
823 case XML_SCHEMA_CONTENT_EMPTY:
824 fprintf(output, "empty ");
825 break;
826 case XML_SCHEMA_CONTENT_ELEMENTS:
827 fprintf(output, "element ");
828 break;
829 case XML_SCHEMA_CONTENT_MIXED:
830 fprintf(output, "mixed ");
831 break;
832 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
833 fprintf(output, "mixed_or_elems ");
834 break;
835 case XML_SCHEMA_CONTENT_BASIC:
836 fprintf(output, "basic ");
837 break;
838 case XML_SCHEMA_CONTENT_SIMPLE:
839 fprintf(output, "simple ");
840 break;
841 case XML_SCHEMA_CONTENT_ANY:
842 fprintf(output, "any ");
843 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000844 }
845 fprintf(output, "\n");
846 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000847 fprintf(output, " ");
848 if (type->minOccurs != 1)
849 fprintf(output, "min: %d ", type->minOccurs);
850 if (type->maxOccurs >= UNBOUNDED)
851 fprintf(output, "max: unbounded\n");
852 else if (type->maxOccurs != 1)
853 fprintf(output, "max: %d\n", type->maxOccurs);
854 else
855 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000856 }
857 if (type->annot != NULL)
858 xmlSchemaAnnotDump(output, type->annot);
859 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000860 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000861
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000862 fprintf(output, " subtypes: ");
863 while (sub != NULL) {
864 fprintf(output, "%s ", sub->name);
865 sub = sub->next;
866 }
867 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000868 }
869
870}
871
872/**
873 * xmlSchemaDump:
874 * @output: the file output
875 * @schema: a schema structure
876 *
877 * Dump a Schema structure.
878 */
879void
880xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
881{
882 if (schema == NULL) {
883 fprintf(output, "Schemas: NULL\n");
884 return;
885 }
886 fprintf(output, "Schemas: ");
887 if (schema->name != NULL)
888 fprintf(output, "%s, ", schema->name);
889 else
890 fprintf(output, "no name, ");
891 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000892 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000893 else
894 fprintf(output, "no target namespace");
895 fprintf(output, "\n");
896 if (schema->annot != NULL)
897 xmlSchemaAnnotDump(output, schema->annot);
898
899 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
900 output);
901 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000902 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000903}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000904#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000905
906/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000907 * *
908 * Utilities *
909 * *
910 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000911
912/**
913 * xmlSchemaGetProp:
914 * @ctxt: the parser context
915 * @node: the node
916 * @name: the property name
917 *
918 * Read a attribute value and internalize the string
919 *
920 * Returns the string or NULL if not present.
921 */
922static const xmlChar *
923xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
924 const char *name)
925{
926 xmlChar *val;
927 const xmlChar *ret;
928
929 val = xmlGetProp(node, BAD_CAST name);
930 if (val == NULL)
931 return(NULL);
932 ret = xmlDictLookup(ctxt->dict, val, -1);
933 xmlFree(val);
934 return(ret);
935}
936
937/**
938 * xmlSchemaGetNamespace:
939 * @ctxt: the parser context
940 * @schema: the schemas containing the declaration
941 * @node: the node
942 * @qname: the QName to analyze
943 *
944 * Find the namespace name for the given declaration.
945 *
946 * Returns the local name for that declaration, as well as the namespace name
947 */
948static const xmlChar *
949xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
950 xmlNodePtr node, const xmlChar *qname,
951 const xmlChar **namespace) {
952 int len;
953 const xmlChar *name, *prefix, *def = NULL;
954 xmlNsPtr ns;
955
956 *namespace = NULL;
957
958 if (xmlStrEqual(node->name, BAD_CAST "element") ||
959 xmlStrEqual(node->name, BAD_CAST "attribute") ||
960 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
961 xmlStrEqual(node->name, BAD_CAST "complexType")) {
962 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
963 }
964
965 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
966 name = xmlSplitQName3(qname, &len);
967 if (name == NULL) {
968 if (def == NULL) {
969 if (xmlStrEqual(node->name, BAD_CAST "element")) {
970 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
971 *namespace = schema->targetNamespace;
972 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
973 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
974 *namespace = schema->targetNamespace;
975 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
976 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
977 *namespace = schema->targetNamespace;
978 }
979 } else {
980 *namespace = def;
981 }
982 return(qname);
983 }
984 name = xmlDictLookup(ctxt->dict, name, -1);
985 prefix = xmlDictLookup(ctxt->dict, qname, len);
986 if (def != NULL) {
987 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
988 "%s: presence of both prefix %s and targetNamespace\n",
989 node->name, prefix);
990 }
991 ns = xmlSearchNs(node->doc, node, prefix);
992 if (ns == NULL) {
993 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
994 "%s: the QName prefix %s is undefined\n",
995 node->name, prefix);
996 return(name);
997 }
998 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
999 return(name);
1000}
1001
1002/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001003 * *
1004 * Parsing functions *
1005 * *
1006 ************************************************************************/
1007
1008/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001009 * xmlSchemaGetElem:
1010 * @schema: the schemas context
1011 * @name: the element name
1012 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001013 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001014 *
1015 * Lookup a an element in the schemas or the accessible schemas
1016 *
1017 * Returns the element definition or NULL if not found.
1018 */
1019static xmlSchemaElementPtr
1020xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001021 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001022{
1023 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001024 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001025
1026 if ((name == NULL) || (schema == NULL))
1027 return (NULL);
1028
1029 if (namespace == NULL) {
1030 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001031 if ((ret != NULL) &&
1032 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001033 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001034 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001035 } else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
1036 if (xmlStrEqual(namespace, schema->targetNamespace))
1037 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1038 else
1039 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001040 if ((ret != NULL) &&
1041 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001042 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001043 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001044 } else {
1045 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001046 if ((ret != NULL) &&
1047 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001048 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001049 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001050 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001051 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001052 import = xmlHashLookup(schema->schemasImports, namespace);
1053 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001054 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001055#ifdef DEBUG
1056 if (ret == NULL) {
1057 if (namespace == NULL)
1058 fprintf(stderr, "Unable to lookup type %s", name);
1059 else
1060 fprintf(stderr, "Unable to lookup type %s:%s", name,
1061 namespace);
1062 }
1063#endif
1064 return (ret);
1065}
1066
1067/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001068 * xmlSchemaGetType:
1069 * @schema: the schemas context
1070 * @name: the type name
1071 * @ns: the type namespace
1072 *
1073 * Lookup a type in the schemas or the predefined types
1074 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001075 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001076 */
1077static xmlSchemaTypePtr
1078xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001079 const xmlChar * namespace)
1080{
Daniel Veillard4255d502002-04-16 15:50:10 +00001081 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001082 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001083
1084 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001085 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001086 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001087 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1088 if (ret != NULL)
1089 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001090 }
1091 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001092 if (ret != NULL)
1093 return (ret);
1094 import = xmlHashLookup(schema->schemasImports, namespace);
1095 if (import != NULL)
1096 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001097#ifdef DEBUG
1098 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001099 if (namespace == NULL)
1100 fprintf(stderr, "Unable to lookup type %s", name);
1101 else
1102 fprintf(stderr, "Unable to lookup type %s:%s", name,
1103 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001104 }
1105#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001106 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001107}
1108
1109/************************************************************************
1110 * *
1111 * Parsing functions *
1112 * *
1113 ************************************************************************/
1114
1115#define IS_BLANK_NODE(n) \
1116 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1117
1118/**
1119 * xmlSchemaIsBlank:
1120 * @str: a string
1121 *
1122 * Check if a string is ignorable
1123 *
1124 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1125 */
1126static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001127xmlSchemaIsBlank(xmlChar * str)
1128{
Daniel Veillard4255d502002-04-16 15:50:10 +00001129 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001130 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001131 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001132 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001133 return (0);
1134 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001135 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001136 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001137}
1138
1139/**
1140 * xmlSchemaAddNotation:
1141 * @ctxt: a schema validation context
1142 * @schema: the schema being built
1143 * @name: the item name
1144 *
1145 * Add an XML schema Attrribute declaration
1146 * *WARNING* this interface is highly subject to change
1147 *
1148 * Returns the new struture or NULL in case of error
1149 */
1150static xmlSchemaNotationPtr
1151xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001152 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001153{
1154 xmlSchemaNotationPtr ret = NULL;
1155 int val;
1156
1157 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1158 return (NULL);
1159
1160 if (schema->notaDecl == NULL)
1161 schema->notaDecl = xmlHashCreate(10);
1162 if (schema->notaDecl == NULL)
1163 return (NULL);
1164
1165 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1166 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001167 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001168 return (NULL);
1169 }
1170 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001171 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001172 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1173 ret);
1174 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001175 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1176 XML_SCHEMAP_REDEFINED_NOTATION,
1177 "Notation %s already defined\n",
1178 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001179 xmlFree(ret);
1180 return (NULL);
1181 }
1182 return (ret);
1183}
1184
1185
1186/**
1187 * xmlSchemaAddAttribute:
1188 * @ctxt: a schema validation context
1189 * @schema: the schema being built
1190 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001191 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001192 *
1193 * Add an XML schema Attrribute declaration
1194 * *WARNING* this interface is highly subject to change
1195 *
1196 * Returns the new struture or NULL in case of error
1197 */
1198static xmlSchemaAttributePtr
1199xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001200 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001201{
1202 xmlSchemaAttributePtr ret = NULL;
1203 int val;
1204
1205 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1206 return (NULL);
1207
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001208#ifdef DEBUG
1209 fprintf(stderr, "Adding attribute %s\n", name);
1210 if (namespace != NULL)
1211 fprintf(stderr, " target namespace %s\n", namespace);
1212#endif
1213
Daniel Veillard4255d502002-04-16 15:50:10 +00001214 if (schema->attrDecl == NULL)
1215 schema->attrDecl = xmlHashCreate(10);
1216 if (schema->attrDecl == NULL)
1217 return (NULL);
1218
1219 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1220 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001221 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001222 return (NULL);
1223 }
1224 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001225 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1226 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001227 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001228 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001229 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001230 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1231 XML_SCHEMAP_REDEFINED_ATTR,
1232 "Attribute %s already defined\n",
1233 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001234 xmlFree(ret);
1235 return (NULL);
1236 }
1237 return (ret);
1238}
1239
1240/**
1241 * xmlSchemaAddAttributeGroup:
1242 * @ctxt: a schema validation context
1243 * @schema: the schema being built
1244 * @name: the item name
1245 *
1246 * Add an XML schema Attrribute Group declaration
1247 *
1248 * Returns the new struture or NULL in case of error
1249 */
1250static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001251xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1252 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001253{
1254 xmlSchemaAttributeGroupPtr ret = NULL;
1255 int val;
1256
1257 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1258 return (NULL);
1259
1260 if (schema->attrgrpDecl == NULL)
1261 schema->attrgrpDecl = xmlHashCreate(10);
1262 if (schema->attrgrpDecl == NULL)
1263 return (NULL);
1264
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001265 ret =
1266 (xmlSchemaAttributeGroupPtr)
1267 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001268 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001269 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001270 return (NULL);
1271 }
1272 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001273 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001274 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001275 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001276 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001277 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1278 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1279 "Attribute group %s already defined\n",
1280 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001281 xmlFree(ret);
1282 return (NULL);
1283 }
1284 return (ret);
1285}
1286
1287/**
1288 * xmlSchemaAddElement:
1289 * @ctxt: a schema validation context
1290 * @schema: the schema being built
1291 * @name: the type name
1292 * @namespace: the type namespace
1293 *
1294 * Add an XML schema Element declaration
1295 * *WARNING* this interface is highly subject to change
1296 *
1297 * Returns the new struture or NULL in case of error
1298 */
1299static xmlSchemaElementPtr
1300xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1301 const xmlChar * name, const xmlChar * namespace)
1302{
1303 xmlSchemaElementPtr ret = NULL;
1304 int val;
1305
1306 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1307 return (NULL);
1308
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001309#ifdef DEBUG
1310 fprintf(stderr, "Adding element %s\n", name);
1311 if (namespace != NULL)
1312 fprintf(stderr, " target namespace %s\n", namespace);
1313#endif
1314
Daniel Veillard4255d502002-04-16 15:50:10 +00001315 if (schema->elemDecl == NULL)
1316 schema->elemDecl = xmlHashCreate(10);
1317 if (schema->elemDecl == NULL)
1318 return (NULL);
1319
1320 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1321 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001322 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001323 return (NULL);
1324 }
1325 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001326 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1327 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001328 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001329 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001330 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001331 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001332
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001333 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001334 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1335 namespace, ret);
1336 if (val != 0) {
1337 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1338 XML_SCHEMAP_REDEFINED_ELEMENT,
1339 "Element %s already defined\n",
1340 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001341 xmlFree(ret);
1342 return (NULL);
1343 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001344 }
1345 return (ret);
1346}
1347
1348/**
1349 * xmlSchemaAddType:
1350 * @ctxt: a schema validation context
1351 * @schema: the schema being built
1352 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001353 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001354 *
1355 * Add an XML schema Simple Type definition
1356 * *WARNING* this interface is highly subject to change
1357 *
1358 * Returns the new struture or NULL in case of error
1359 */
1360static xmlSchemaTypePtr
1361xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001362 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001363{
1364 xmlSchemaTypePtr ret = NULL;
1365 int val;
1366
1367 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1368 return (NULL);
1369
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001370#ifdef DEBUG
1371 fprintf(stderr, "Adding type %s\n", name);
1372 if (namespace != NULL)
1373 fprintf(stderr, " target namespace %s\n", namespace);
1374#endif
1375
Daniel Veillard4255d502002-04-16 15:50:10 +00001376 if (schema->typeDecl == NULL)
1377 schema->typeDecl = xmlHashCreate(10);
1378 if (schema->typeDecl == NULL)
1379 return (NULL);
1380
1381 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1382 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001383 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001384 return (NULL);
1385 }
1386 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001387 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001388 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001389 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001390 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001391 if (ctxt->includes == 0) {
1392 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1393 XML_SCHEMAP_REDEFINED_TYPE,
1394 "Type %s already defined\n",
1395 name, NULL);
1396 xmlFree(ret);
1397 return (NULL);
1398 } else {
1399 xmlSchemaTypePtr prev;
1400
1401 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1402 if (prev == NULL) {
1403 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1404 XML_ERR_INTERNAL_ERROR,
1405 "Internal error on type %s definition\n",
1406 name, NULL);
1407 xmlFree(ret);
1408 return (NULL);
1409 }
1410 ret->redef = prev->redef;
1411 prev->redef = ret;
1412 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001413 }
1414 ret->minOccurs = 1;
1415 ret->maxOccurs = 1;
1416
1417 return (ret);
1418}
1419
1420/**
1421 * xmlSchemaAddGroup:
1422 * @ctxt: a schema validation context
1423 * @schema: the schema being built
1424 * @name: the group name
1425 *
1426 * Add an XML schema Group definition
1427 *
1428 * Returns the new struture or NULL in case of error
1429 */
1430static xmlSchemaTypePtr
1431xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001432 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001433{
1434 xmlSchemaTypePtr ret = NULL;
1435 int val;
1436
1437 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1438 return (NULL);
1439
1440 if (schema->groupDecl == NULL)
1441 schema->groupDecl = xmlHashCreate(10);
1442 if (schema->groupDecl == NULL)
1443 return (NULL);
1444
1445 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1446 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001447 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001448 return (NULL);
1449 }
1450 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001451 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 val =
1453 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1454 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001455 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001456 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1457 XML_SCHEMAP_REDEFINED_GROUP,
1458 "Group %s already defined\n",
1459 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001460 xmlFree(ret);
1461 return (NULL);
1462 }
1463 ret->minOccurs = 1;
1464 ret->maxOccurs = 1;
1465
1466 return (ret);
1467}
1468
1469/************************************************************************
1470 * *
1471 * Utilities for parsing *
1472 * *
1473 ************************************************************************/
1474
1475/**
1476 * xmlGetQNameProp:
1477 * @ctxt: a schema validation context
1478 * @node: a subtree containing XML Schema informations
1479 * @name: the attribute name
1480 * @namespace: the result namespace if any
1481 *
1482 * Extract a QName Attribute value
1483 *
1484 * Returns the NCName or NULL if not found, and also update @namespace
1485 * with the namespace URI
1486 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001487static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001488xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001489 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001490{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001491 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001492 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001493 const xmlChar *ret, *prefix;
1494 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001495
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001496 *namespace = NULL;
1497 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001498 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001499 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001500
Daniel Veillardba0153a2004-04-01 10:42:31 +00001501 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00001502 ns = xmlSearchNs(node->doc, node, 0);
1503 if (ns) {
1504 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1505 return (val);
1506 }
1507 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001508 ret = xmlSplitQName3(val, &len);
1509 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001510 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001511 }
1512 ret = xmlDictLookup(ctxt->dict, ret, -1);
1513 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001514
1515 ns = xmlSearchNs(node->doc, node, prefix);
1516 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001517 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1518 "Attribute %s: the QName prefix %s is undefined\n",
1519 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001520 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001521 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001522 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001523 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001524}
1525
1526/**
1527 * xmlGetMaxOccurs:
1528 * @ctxt: a schema validation context
1529 * @node: a subtree containing XML Schema informations
1530 *
1531 * Get the maxOccurs property
1532 *
1533 * Returns the default if not found, or the value
1534 */
1535static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001536xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1537{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001538 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001539 int ret = 0;
1540
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001541 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001542 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001543 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001544
1545 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001546 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001547 }
1548
1549 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001550 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001551 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001552 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001553 ret = ret * 10 + (*cur - '0');
1554 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001555 }
William M. Brack76e95df2003-10-18 16:20:14 +00001556 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001557 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001558 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001559 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1560 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001561 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001562 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001563 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001564}
1565
1566/**
1567 * xmlGetMinOccurs:
1568 * @ctxt: a schema validation context
1569 * @node: a subtree containing XML Schema informations
1570 *
1571 * Get the minOccurs property
1572 *
1573 * Returns the default if not found, or the value
1574 */
1575static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1577{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001578 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001579 int ret = 0;
1580
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001581 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001582 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001583 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001584
1585 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001586 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001587 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001588 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001589 ret = ret * 10 + (*cur - '0');
1590 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001591 }
William M. Brack76e95df2003-10-18 16:20:14 +00001592 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001593 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001594 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001595 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1596 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001597 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001598 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001599 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001600}
1601
1602/**
1603 * xmlGetBooleanProp:
1604 * @ctxt: a schema validation context
1605 * @node: a subtree containing XML Schema informations
1606 * @name: the attribute name
1607 * @def: the default value
1608 *
1609 * Get is a bolean property is set
1610 *
1611 * Returns the default if not found, 0 if found to be false,
1612 * 1 if found to be true
1613 */
1614static int
1615xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 const char *name, int def)
1617{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001618 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001619
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001620 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001621 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001622 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001623
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001624 if (xmlStrEqual(val, BAD_CAST "true"))
1625 def = 1;
1626 else if (xmlStrEqual(val, BAD_CAST "false"))
1627 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001628 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001629 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1630 "Attribute %s: the value %s is not boolean\n",
1631 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001632 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001633 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001634}
1635
1636/************************************************************************
1637 * *
1638 * Shema extraction from an Infoset *
1639 * *
1640 ************************************************************************/
1641static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1642 ctxt, xmlSchemaPtr schema,
1643 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001644static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1645 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001646 xmlSchemaPtr schema,
1647 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001648static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1649 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001650 xmlSchemaPtr schema,
1651 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001652 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001653static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1654 xmlSchemaPtr schema,
1655 xmlNodePtr node);
1656static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1657 xmlSchemaPtr schema,
1658 xmlNodePtr node);
1659static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1660 ctxt,
1661 xmlSchemaPtr schema,
1662 xmlNodePtr node);
1663static xmlSchemaAttributeGroupPtr
1664xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1665 xmlSchemaPtr schema, xmlNodePtr node);
1666static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1667 xmlSchemaPtr schema,
1668 xmlNodePtr node);
1669static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1670 xmlSchemaPtr schema,
1671 xmlNodePtr node);
1672static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001673xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1674 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001675
1676/**
1677 * xmlSchemaParseAttrDecls:
1678 * @ctxt: a schema validation context
1679 * @schema: the schema being built
1680 * @node: a subtree containing XML Schema informations
1681 * @type: the hosting type
1682 *
1683 * parse a XML schema attrDecls declaration corresponding to
1684 * <!ENTITY % attrDecls
1685 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1686 */
1687static xmlNodePtr
1688xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1689 xmlNodePtr child, xmlSchemaTypePtr type)
1690{
1691 xmlSchemaAttributePtr lastattr, attr;
1692
1693 lastattr = NULL;
1694 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001695 (IS_SCHEMA(child, "attributeGroup"))) {
1696 attr = NULL;
1697 if (IS_SCHEMA(child, "attribute")) {
1698 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1699 } else if (IS_SCHEMA(child, "attributeGroup")) {
1700 attr = (xmlSchemaAttributePtr)
1701 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1702 }
1703 if (attr != NULL) {
1704 if (lastattr == NULL) {
1705 type->attributes = attr;
1706 lastattr = attr;
1707 } else {
1708 lastattr->next = attr;
1709 lastattr = attr;
1710 }
1711 }
1712 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001713 }
1714 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001715 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1716 if (attr != NULL) {
1717 if (lastattr == NULL) {
1718 type->attributes = attr;
1719 lastattr = attr;
1720 } else {
1721 lastattr->next = attr;
1722 lastattr = attr;
1723 }
1724 }
1725 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001726 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001727 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001728}
1729
1730/**
1731 * xmlSchemaParseAnnotation:
1732 * @ctxt: a schema validation context
1733 * @schema: the schema being built
1734 * @node: a subtree containing XML Schema informations
1735 *
1736 * parse a XML schema Attrribute declaration
1737 * *WARNING* this interface is highly subject to change
1738 *
1739 * Returns -1 in case of error, 0 if the declaration is inproper and
1740 * 1 in case of success.
1741 */
1742static xmlSchemaAnnotPtr
1743xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1744 xmlNodePtr node)
1745{
1746 xmlSchemaAnnotPtr ret;
1747
1748 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1749 return (NULL);
1750 ret = xmlSchemaNewAnnot(ctxt, node);
1751
1752 return (ret);
1753}
1754
1755/**
1756 * xmlSchemaParseFacet:
1757 * @ctxt: a schema validation context
1758 * @schema: the schema being built
1759 * @node: a subtree containing XML Schema informations
1760 *
1761 * parse a XML schema Facet declaration
1762 * *WARNING* this interface is highly subject to change
1763 *
1764 * Returns the new type structure or NULL in case of error
1765 */
1766static xmlSchemaFacetPtr
1767xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001768 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001769{
1770 xmlSchemaFacetPtr facet;
1771 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001772 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001773
1774 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1775 return (NULL);
1776
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001777 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001778 if (facet == NULL) {
1779 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1780 return (NULL);
1781 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001782 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001783 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001784 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001785 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1786 "Facet %s has no value\n", node->name, NULL);
1787 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001788 return (NULL);
1789 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001790 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001791 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001792 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001793 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001794 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001795 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001796 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001797 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001798 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001799 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001800 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001801 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001802 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001803 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001804 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001805 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001806 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001807 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001808 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001809 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001810 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001811 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1812 } else if (IS_SCHEMA(node, "minLength")) {
1813 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1814 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001815 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1816 "Unknown facet type %s\n", node->name, NULL);
1817 xmlSchemaFreeFacet(facet);
1818 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001820 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001821 facet->value = value;
1822 child = node->children;
1823
1824 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001825 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1826 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001827 }
1828 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001829 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1830 "Facet %s has unexpected child content\n",
1831 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001832 }
1833 return (facet);
1834}
1835
1836/**
1837 * xmlSchemaParseAny:
1838 * @ctxt: a schema validation context
1839 * @schema: the schema being built
1840 * @node: a subtree containing XML Schema informations
1841 *
1842 * parse a XML schema Any declaration
1843 * *WARNING* this interface is highly subject to change
1844 *
1845 * Returns the new type structure or NULL in case of error
1846 */
1847static xmlSchemaTypePtr
1848xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1849 xmlNodePtr node)
1850{
1851 xmlSchemaTypePtr type;
1852 xmlNodePtr child = NULL;
1853 xmlChar name[30];
1854
1855 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1856 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001857 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001858 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001859 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001860 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001861 type->node = node;
1862 type->type = XML_SCHEMA_TYPE_ANY;
1863 child = node->children;
1864 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1865 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1866
1867 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001868 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1869 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001870 }
1871 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001872 xmlSchemaPErr2(ctxt, node, child,
1873 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1874 "Sequence %s has unexpected content\n", type->name,
1875 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001876 }
1877
1878 return (type);
1879}
1880
1881/**
1882 * xmlSchemaParseNotation:
1883 * @ctxt: a schema validation context
1884 * @schema: the schema being built
1885 * @node: a subtree containing XML Schema informations
1886 *
1887 * parse a XML schema Notation declaration
1888 *
1889 * Returns the new structure or NULL in case of error
1890 */
1891static xmlSchemaNotationPtr
1892xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001893 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001894{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001895 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001896 xmlSchemaNotationPtr ret;
1897 xmlNodePtr child = NULL;
1898
1899 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1900 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001901 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001902 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001903 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1904 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001905 return (NULL);
1906 }
1907 ret = xmlSchemaAddNotation(ctxt, schema, name);
1908 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001909 return (NULL);
1910 }
1911 child = node->children;
1912 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001913 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1914 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001915 }
1916 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001917 xmlSchemaPErr2(ctxt, node, child,
1918 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1919 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001920 }
1921
1922 return (ret);
1923}
1924
1925/**
1926 * xmlSchemaParseAnyAttribute:
1927 * @ctxt: a schema validation context
1928 * @schema: the schema being built
1929 * @node: a subtree containing XML Schema informations
1930 *
1931 * parse a XML schema AnyAttrribute declaration
1932 * *WARNING* this interface is highly subject to change
1933 *
1934 * Returns an attribute def structure or NULL
1935 */
1936static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001937xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1938 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001939{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001940 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001941 xmlSchemaAttributePtr ret;
1942 xmlNodePtr child = NULL;
1943 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001944 const xmlChar *local, *ns;
1945
Daniel Veillard4255d502002-04-16 15:50:10 +00001946
1947 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1948 return (NULL);
1949
1950 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001951 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1952 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001953 if (ret == NULL) {
1954 return (NULL);
1955 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001956 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1957 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001958 if ((processContents == NULL)
1959 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1960 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1961 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1962 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1963 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1964 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001965 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001966 xmlSchemaPErr2(ctxt, node, child,
1967 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1968 "anyAttribute has unexpected content for processContents: %s\n",
1969 processContents, NULL);
1970 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001971 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001972
1973 child = node->children;
1974 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001975 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1976 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001977 }
1978 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001979 xmlSchemaPErr2(ctxt, node, child,
1980 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1981 "anyAttribute %s has unexpected content\n",
1982 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001983 }
1984
1985 return (ret);
1986}
1987
1988
1989/**
1990 * xmlSchemaParseAttribute:
1991 * @ctxt: a schema validation context
1992 * @schema: the schema being built
1993 * @node: a subtree containing XML Schema informations
1994 *
1995 * parse a XML schema Attrribute declaration
1996 * *WARNING* this interface is highly subject to change
1997 *
1998 * Returns -1 in case of error, 0 if the declaration is inproper and
1999 * 1 in case of success.
2000 */
2001static xmlSchemaAttributePtr
2002xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2003 xmlNodePtr node)
2004{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002005 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002006 xmlSchemaAttributePtr ret;
2007 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002008 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002009
2010 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2011 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002012 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002013 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002014
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002015 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2016 if (ref == NULL) {
2017 xmlSchemaPErr2(ctxt, node, child,
2018 XML_SCHEMAP_ATTR_NONAME_NOREF,
2019 "Attribute has no name nor ref\n", NULL, NULL);
2020 return (NULL);
2021 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002022 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2023 name = (const xmlChar *) buf;
2024 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2025 } else {
2026 const xmlChar *local, *ns;
2027
2028 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2029 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002030 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002031 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002032 return (NULL);
2033 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002034
2035 /* Read the "use" attribute. */
2036 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2037 if (attrVal != NULL) {
2038 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2039 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2040 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2041 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2042 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2043 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2044 else
2045 xmlSchemaPErr(ctxt, node,
2046 XML_SCHEMAP_INVALID_ATTR_USE,
2047 "attribute %s has an invalid value for \"use\"\n", name, NULL);
2048 } else
2049 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2050
Daniel Veillard4255d502002-04-16 15:50:10 +00002051 ret->ref = ref;
2052 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002053 if ((ret->targetNamespace != NULL) &&
2054 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2055 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2056 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002057 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002058 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002059 child = node->children;
2060 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002061 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2062 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002063 }
2064 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002065 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2066 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002067 }
2068 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002069 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2070 "attribute %s has unexpected content\n", name,
2071 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002072 }
2073
2074 return (ret);
2075}
2076
2077/**
2078 * xmlSchemaParseAttributeGroup:
2079 * @ctxt: a schema validation context
2080 * @schema: the schema being built
2081 * @node: a subtree containing XML Schema informations
2082 *
2083 * parse a XML schema Attribute Group declaration
2084 * *WARNING* this interface is highly subject to change
2085 *
2086 * Returns the attribute group or NULL in case of error.
2087 */
2088static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002089xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2090 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002091{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002092 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002093 xmlSchemaAttributeGroupPtr ret;
2094 xmlSchemaAttributePtr last = NULL, attr;
2095 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002096 const xmlChar *oldcontainer;
2097 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002098
2099 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2100 return (NULL);
2101 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002102 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002103 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002104
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002105 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2106 if (ref == NULL) {
2107 xmlSchemaPErr2(ctxt, node, child,
2108 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2109 "AttributeGroup has no name nor ref\n", NULL,
2110 NULL);
2111 return (NULL);
2112 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002113 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2114 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002115 if (name == NULL) {
2116 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2117 return (NULL);
2118 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002119 }
2120 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2121 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002122 return (NULL);
2123 }
2124 ret->ref = ref;
2125 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002126 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002127 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002128 child = node->children;
2129 ctxt->container = name;
2130 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002131 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2132 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 }
2134 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002135 (IS_SCHEMA(child, "attributeGroup"))) {
2136 attr = NULL;
2137 if (IS_SCHEMA(child, "attribute")) {
2138 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2139 } else if (IS_SCHEMA(child, "attributeGroup")) {
2140 attr = (xmlSchemaAttributePtr)
2141 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2142 }
2143 if (attr != NULL) {
2144 if (last == NULL) {
2145 ret->attributes = attr;
2146 last = attr;
2147 } else {
2148 last->next = attr;
2149 last = attr;
2150 }
2151 }
2152 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002153 }
2154 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002155 TODO
2156 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002157 }
2158 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002159 xmlSchemaPErr2(ctxt, node, child,
2160 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2161 "attribute group %s has unexpected content\n", name,
2162 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002163 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002164 ctxt->container = oldcontainer;
2165 return (ret);
2166}
2167
2168/**
2169 * xmlSchemaParseElement:
2170 * @ctxt: a schema validation context
2171 * @schema: the schema being built
2172 * @node: a subtree containing XML Schema informations
2173 *
2174 * parse a XML schema Element declaration
2175 * *WARNING* this interface is highly subject to change
2176 *
2177 * Returns -1 in case of error, 0 if the declaration is inproper and
2178 * 1 in case of success.
2179 */
2180static xmlSchemaElementPtr
2181xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2182 xmlNodePtr node, int toplevel)
2183{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002184 const xmlChar *name, *fixed;
2185 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002186 xmlSchemaElementPtr ret;
2187 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002188 const xmlChar *oldcontainer;
2189 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002190
2191 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2192 return (NULL);
2193 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002194 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002195 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002196
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002197 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2198 if (ref == NULL) {
2199 xmlSchemaPErr2(ctxt, node, child,
2200 XML_SCHEMAP_ELEM_NONAME_NOREF,
2201 "Element has no name nor ref\n", NULL, NULL);
2202 return (NULL);
2203 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002204 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2205 name = (const xmlChar *) buf;
2206 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2207 } else {
2208 const xmlChar *local, *ns;
2209
2210 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2211 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002212 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002213 if (ret != NULL)
2214 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002215 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002216 return (NULL);
2217 }
2218 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2219 ret->ref = ref;
2220 ret->refNs = refNs;
2221 if (ref != NULL)
2222 ret->flags |= XML_SCHEMAS_ELEM_REF;
2223 if (toplevel)
2224 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2225 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2226 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2227 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2228 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2229 ctxt->container = name;
2230
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002231 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002232 ret->namedType =
2233 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
2234 ret->substGroup =
2235 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2236 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002237 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002238 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2239 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002240
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002241 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002242 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2244 "Element %s has both default and fixed\n",
2245 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 } else if (fixed != NULL) {
2247 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002249 }
2250
2251 child = node->children;
2252 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2254 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002255 }
2256 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002257 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002258 child = child->next;
2259 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002260 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002261 child = child->next;
2262 }
2263 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002264 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2265 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002266 }
2267 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002268 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2269 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002270 }
2271
2272 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002273 return (ret);
2274}
2275
2276/**
2277 * xmlSchemaParseUnion:
2278 * @ctxt: a schema validation context
2279 * @schema: the schema being built
2280 * @node: a subtree containing XML Schema informations
2281 *
2282 * parse a XML schema Union definition
2283 * *WARNING* this interface is highly subject to change
2284 *
2285 * Returns -1 in case of error, 0 if the declaration is inproper and
2286 * 1 in case of success.
2287 */
2288static xmlSchemaTypePtr
2289xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002290 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002291{
2292 xmlSchemaTypePtr type, subtype, last = NULL;
2293 xmlNodePtr child = NULL;
2294 xmlChar name[30];
2295
2296 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2297 return (NULL);
2298
2299
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002300 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002301 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002302 if (type == NULL)
2303 return (NULL);
2304 type->node = node;
Daniel Veillard377e1a92004-04-16 16:30:05 +00002305 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002306 type->id = xmlSchemaGetProp(ctxt, node, "id");
2307 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002308
2309 child = node->children;
2310 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002311 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2312 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002313 }
2314 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002315 subtype = (xmlSchemaTypePtr)
2316 xmlSchemaParseSimpleType(ctxt, schema, child);
2317 if (subtype != NULL) {
2318 if (last == NULL) {
2319 type->subtypes = subtype;
2320 last = subtype;
2321 } else {
2322 last->next = subtype;
2323 last = subtype;
2324 }
2325 last->next = NULL;
2326 }
2327 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002328 }
2329 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002330 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2331 "Union %s has unexpected content\n", type->name,
2332 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002333 }
2334 return (type);
2335}
2336
2337/**
2338 * xmlSchemaParseList:
2339 * @ctxt: a schema validation context
2340 * @schema: the schema being built
2341 * @node: a subtree containing XML Schema informations
2342 *
2343 * parse a XML schema List definition
2344 * *WARNING* this interface is highly subject to change
2345 *
2346 * Returns -1 in case of error, 0 if the declaration is inproper and
2347 * 1 in case of success.
2348 */
2349static xmlSchemaTypePtr
2350xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002351 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002352{
2353 xmlSchemaTypePtr type, subtype;
2354 xmlNodePtr child = NULL;
2355 xmlChar name[30];
2356
2357 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2358 return (NULL);
2359
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002360 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002361 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002362 if (type == NULL)
2363 return (NULL);
2364 type->node = node;
2365 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002366 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002367 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2368
2369 child = node->children;
2370 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002371 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2372 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002373 }
2374 subtype = NULL;
2375 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002376 subtype = (xmlSchemaTypePtr)
2377 xmlSchemaParseSimpleType(ctxt, schema, child);
2378 child = child->next;
2379 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002380 }
2381 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002382 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2383 "List %s has unexpected content\n", type->name,
2384 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002385 }
2386 return (type);
2387}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002388
Daniel Veillard4255d502002-04-16 15:50:10 +00002389/**
2390 * xmlSchemaParseSimpleType:
2391 * @ctxt: a schema validation context
2392 * @schema: the schema being built
2393 * @node: a subtree containing XML Schema informations
2394 *
2395 * parse a XML schema Simple Type definition
2396 * *WARNING* this interface is highly subject to change
2397 *
2398 * Returns -1 in case of error, 0 if the declaration is inproper and
2399 * 1 in case of success.
2400 */
2401static xmlSchemaTypePtr
2402xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2403 xmlNodePtr node)
2404{
2405 xmlSchemaTypePtr type, subtype;
2406 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002407 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002408
2409 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2410 return (NULL);
2411
2412
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002413 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002414 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002416
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002417 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2418 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2419 } else {
2420 const xmlChar *local, *ns;
2421
2422 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2423 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002424 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002425 if (type == NULL)
2426 return (NULL);
2427 type->node = node;
2428 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002429 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002430
2431 child = node->children;
2432 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002433 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2434 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002435 }
2436 subtype = NULL;
2437 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002438 subtype = (xmlSchemaTypePtr)
2439 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2440 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002441 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002442 subtype = (xmlSchemaTypePtr)
2443 xmlSchemaParseList(ctxt, schema, child);
2444 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002445 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002446 subtype = (xmlSchemaTypePtr)
2447 xmlSchemaParseUnion(ctxt, schema, child);
2448 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002449 }
2450 type->subtypes = subtype;
2451 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002452 xmlSchemaPErr2(ctxt, node, child,
2453 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2454 "SimpleType %s has unexpected content\n",
2455 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002456 }
2457
2458 return (type);
2459}
2460
2461
2462/**
2463 * xmlSchemaParseGroup:
2464 * @ctxt: a schema validation context
2465 * @schema: the schema being built
2466 * @node: a subtree containing XML Schema informations
2467 *
2468 * parse a XML schema Group definition
2469 * *WARNING* this interface is highly subject to change
2470 *
2471 * Returns -1 in case of error, 0 if the declaration is inproper and
2472 * 1 in case of success.
2473 */
2474static xmlSchemaTypePtr
2475xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002476 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002477{
2478 xmlSchemaTypePtr type, subtype;
2479 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002480 const xmlChar *name;
2481 const xmlChar *ref = NULL, *refNs = NULL;
2482 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002483
2484 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2485 return (NULL);
2486
2487
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002488 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002489 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002491 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2492 if (ref == NULL) {
2493 xmlSchemaPErr2(ctxt, node, child,
2494 XML_SCHEMAP_GROUP_NONAME_NOREF,
2495 "Group has no name nor ref\n", NULL, NULL);
2496 return (NULL);
2497 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002498 if (refNs == NULL)
2499 refNs = schema->targetNamespace;
2500 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2501 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002502 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002503 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002504 if (type == NULL)
2505 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002506
Daniel Veillard4255d502002-04-16 15:50:10 +00002507 type->node = node;
2508 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002509 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002510 type->ref = ref;
2511 type->refNs = refNs;
2512 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2513 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2514
2515 child = node->children;
2516 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002517 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2518 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002519 }
2520 subtype = NULL;
2521 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002522 subtype = (xmlSchemaTypePtr)
2523 xmlSchemaParseAll(ctxt, schema, child);
2524 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002525 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002526 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2527 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002528 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002529 subtype = (xmlSchemaTypePtr)
2530 xmlSchemaParseSequence(ctxt, schema, child);
2531 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002532 }
2533 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002534 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002535 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002536 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2537 "Group %s has unexpected content\n", type->name,
2538 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002539 }
2540
2541 return (type);
2542}
2543
2544/**
2545 * xmlSchemaParseAll:
2546 * @ctxt: a schema validation context
2547 * @schema: the schema being built
2548 * @node: a subtree containing XML Schema informations
2549 *
2550 * parse a XML schema All definition
2551 * *WARNING* this interface is highly subject to change
2552 *
2553 * Returns -1 in case of error, 0 if the declaration is inproper and
2554 * 1 in case of success.
2555 */
2556static xmlSchemaTypePtr
2557xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002558 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002559{
2560 xmlSchemaTypePtr type, subtype, last = NULL;
2561 xmlNodePtr child = NULL;
2562 xmlChar name[30];
2563
2564 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2565 return (NULL);
2566
2567
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002568 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002569 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002570 if (type == NULL)
2571 return (NULL);
2572 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002573 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002574 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002575 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002576 if (type->minOccurs > 1)
2577 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2578 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002579 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002580 if (type->maxOccurs > 1)
2581 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2582 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002583
2584 child = node->children;
2585 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002586 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2587 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002588 }
2589 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002590 subtype = (xmlSchemaTypePtr)
2591 xmlSchemaParseElement(ctxt, schema, child, 0);
2592 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002593 if (subtype->minOccurs > 1)
2594 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2595 "invalid value for minOccurs (must be 0 or 1)\n",
2596 NULL, NULL);
2597 if (subtype->maxOccurs > 1)
2598 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2599 "invalid value for maxOccurs (must be 0 or 1)\n",
2600 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002601 if (last == NULL) {
2602 type->subtypes = subtype;
2603 last = subtype;
2604 } else {
2605 last->next = subtype;
2606 last = subtype;
2607 }
2608 last->next = NULL;
2609 }
2610 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002611 }
2612 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002613 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2614 "All %s has unexpected content\n", type->name,
2615 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002616 }
2617
2618 return (type);
2619}
2620
2621/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002622 * xmlSchemaImportSchema
2623 *
2624 * @ctxt: a schema validation context
2625 * @schemaLocation: an URI defining where to find the imported schema
2626 *
2627 * import a XML schema
2628 * *WARNING* this interface is highly subject to change
2629 *
2630 * Returns -1 in case of error and 1 in case of success.
2631 */
2632static xmlSchemaImportPtr
2633xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2634 const xmlChar *schemaLocation)
2635{
2636 xmlSchemaImportPtr import;
2637 xmlSchemaParserCtxtPtr newctxt;
2638
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002639 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002640 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002641 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002642 NULL);
2643 return (NULL);
2644 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002645 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2646 /* Keep the same dictionnary for parsing, really */
2647 xmlDictReference(ctxt->dict);
2648 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002649 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002650 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2651
Daniel Veillard1d913862003-11-21 00:28:39 +00002652 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2653 ctxt->userData);
2654
2655 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2656 if (import == NULL) {
2657 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2658 NULL);
2659 xmlSchemaFreeParserCtxt(newctxt);
2660 return (NULL);
2661 }
2662
2663 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002664 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002665 import->schema = xmlSchemaParse(newctxt);
2666
2667 if (import->schema == NULL) {
2668 /* FIXME use another error enum here ? */
2669 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2670 "failed to import schema at location %s\n",
2671 schemaLocation, NULL);
2672
2673 xmlSchemaFreeParserCtxt(newctxt);
2674 if (import->schemaLocation != NULL)
2675 xmlFree((xmlChar *)import->schemaLocation);
2676 xmlFree(import);
2677 return NULL;
2678 }
2679
2680 xmlSchemaFreeParserCtxt(newctxt);
2681 return import;
2682}
2683
2684
2685/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002686 * xmlSchemaParseImport:
2687 * @ctxt: a schema validation context
2688 * @schema: the schema being built
2689 * @node: a subtree containing XML Schema informations
2690 *
2691 * parse a XML schema Import definition
2692 * *WARNING* this interface is highly subject to change
2693 *
2694 * Returns -1 in case of error, 0 if the declaration is inproper and
2695 * 1 in case of success.
2696 */
2697static int
2698xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002699 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002700{
2701 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002702 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002703 const xmlChar *namespace;
2704 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002705 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002706 xmlURIPtr check;
2707
Daniel Veillard1d913862003-11-21 00:28:39 +00002708
Daniel Veillard5a872412002-05-22 06:40:27 +00002709 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2710 return (-1);
2711
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002712 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002713 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002714 check = xmlParseURI((const char *) namespace);
2715 if (check == NULL) {
2716 xmlSchemaPErr2(ctxt, node, child,
2717 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2718 "Import namespace attribute is not an URI: %s\n",
2719 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002720 return (-1);
2721 } else {
2722 xmlFreeURI(check);
2723 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002724 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002725 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002726 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002727 xmlChar *base = NULL;
2728 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002729 check = xmlParseURI((const char *) schemaLocation);
2730 if (check == NULL) {
2731 xmlSchemaPErr2(ctxt, node, child,
2732 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2733 "Import schemaLocation attribute is not an URI: %s\n",
2734 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002735 return (-1);
2736 } else {
2737 xmlFreeURI(check);
2738 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002739 base = xmlNodeGetBase(node->doc, node);
2740 if (base == NULL) {
2741 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2742 } else {
2743 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002744 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002745 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002746 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002747 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2748 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002749 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002750 }
2751 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002752 schema->schemasImports = xmlHashCreate(10);
2753 if (schema->schemasImports == NULL) {
2754 xmlSchemaPErr2(ctxt, node, child,
2755 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2756 "Internal: failed to build import table\n",
2757 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002758 return (-1);
2759 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002760 }
2761 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002762 import = xmlHashLookup(schema->schemasImports,
2763 XML_SCHEMAS_DEFAULT_NAMESPACE);
2764 if (import != NULL)
2765 previous = import->schemaLocation;
2766 else
2767 previous = NULL;
2768
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002769 if (schemaLocation != NULL) {
2770 if (previous != NULL) {
2771 if (!xmlStrEqual(schemaLocation, previous)) {
2772 xmlSchemaPErr2(ctxt, node, child,
2773 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2774 "Redefining import for default namespace with a different URI: %s\n",
2775 schemaLocation, NULL);
2776 }
2777 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002778 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2779 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002780 return (-1);
2781 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002782 xmlHashAddEntry(schema->schemasImports,
2783 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002784 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002785 }
2786 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002787 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002788 import = xmlHashLookup(schema->schemasImports, namespace);
2789 if (import != NULL)
2790 previous = import->schemaLocation;
2791 else
2792 previous = NULL;
2793
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002794 if (schemaLocation != NULL) {
2795 if (previous != NULL) {
2796 if (!xmlStrEqual(schemaLocation, previous)) {
2797 xmlSchemaPErr2(ctxt, node, child,
2798 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2799 "Redefining import for namespace %s with a different URI: %s\n",
2800 namespace, schemaLocation);
2801 }
2802 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002803 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2804 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002805 return (-1);
2806 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002807 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002808 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002809 }
2810 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002811 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002812
2813 child = node->children;
2814 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002815 /*
2816 * the annotations here are simply discarded ...
2817 */
2818 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002819 }
2820 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002821 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2822 "Import has unexpected content\n", NULL, NULL);
2823 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002824 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002825 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002826}
2827
2828/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002829 * xmlSchemaCleanupDoc:
2830 * @ctxt: a schema validation context
2831 * @node: the root of the document.
2832 *
2833 * removes unwanted nodes in a schemas document tree
2834 */
2835static void
2836xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
2837{
2838 xmlNodePtr delete, cur;
2839
2840 if ((ctxt == NULL) || (root == NULL)) return;
2841
2842 /*
2843 * Remove all the blank text nodes
2844 */
2845 delete = NULL;
2846 cur = root;
2847 while (cur != NULL) {
2848 if (delete != NULL) {
2849 xmlUnlinkNode(delete);
2850 xmlFreeNode(delete);
2851 delete = NULL;
2852 }
2853 if (cur->type == XML_TEXT_NODE) {
2854 if (IS_BLANK_NODE(cur)) {
2855 if (xmlNodeGetSpacePreserve(cur) != 1) {
2856 delete = cur;
2857 }
2858 }
2859 } else if ((cur->type != XML_ELEMENT_NODE) &&
2860 (cur->type != XML_CDATA_SECTION_NODE)) {
2861 delete = cur;
2862 goto skip_children;
2863 }
2864
2865 /*
2866 * Skip to next node
2867 */
2868 if (cur->children != NULL) {
2869 if ((cur->children->type != XML_ENTITY_DECL) &&
2870 (cur->children->type != XML_ENTITY_REF_NODE) &&
2871 (cur->children->type != XML_ENTITY_NODE)) {
2872 cur = cur->children;
2873 continue;
2874 }
2875 }
2876 skip_children:
2877 if (cur->next != NULL) {
2878 cur = cur->next;
2879 continue;
2880 }
2881
2882 do {
2883 cur = cur->parent;
2884 if (cur == NULL)
2885 break;
2886 if (cur == root) {
2887 cur = NULL;
2888 break;
2889 }
2890 if (cur->next != NULL) {
2891 cur = cur->next;
2892 break;
2893 }
2894 } while (cur != NULL);
2895 }
2896 if (delete != NULL) {
2897 xmlUnlinkNode(delete);
2898 xmlFreeNode(delete);
2899 delete = NULL;
2900 }
2901}
2902
2903/**
2904 * xmlSchemaParseSchemaTopLevel:
2905 * @ctxt: a schema validation context
2906 * @schema: the schemas
2907 * @nodes: the list of top level nodes
2908 *
2909 * Returns the internal XML Schema structure built from the resource or
2910 * NULL in case of error
2911 */
2912static void
2913xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
2914 xmlSchemaPtr schema, xmlNodePtr nodes)
2915{
2916 xmlNodePtr child;
2917 xmlSchemaAnnotPtr annot;
2918
2919 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
2920 return;
2921
2922 child = nodes;
2923 while ((IS_SCHEMA(child, "include")) ||
2924 (IS_SCHEMA(child, "import")) ||
2925 (IS_SCHEMA(child, "redefine")) ||
2926 (IS_SCHEMA(child, "annotation"))) {
2927 if (IS_SCHEMA(child, "annotation")) {
2928 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2929 if (schema->annot == NULL)
2930 schema->annot = annot;
2931 else
2932 xmlSchemaFreeAnnot(annot);
2933 } else if (IS_SCHEMA(child, "import")) {
2934 xmlSchemaParseImport(ctxt, schema, child);
2935 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002936 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002937 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002938 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002939 } else if (IS_SCHEMA(child, "redefine")) {
2940 TODO
2941 }
2942 child = child->next;
2943 }
2944 while (child != NULL) {
2945 if (IS_SCHEMA(child, "complexType")) {
2946 xmlSchemaParseComplexType(ctxt, schema, child);
2947 child = child->next;
2948 } else if (IS_SCHEMA(child, "simpleType")) {
2949 xmlSchemaParseSimpleType(ctxt, schema, child);
2950 child = child->next;
2951 } else if (IS_SCHEMA(child, "element")) {
2952 xmlSchemaParseElement(ctxt, schema, child, 1);
2953 child = child->next;
2954 } else if (IS_SCHEMA(child, "attribute")) {
2955 xmlSchemaParseAttribute(ctxt, schema, child);
2956 child = child->next;
2957 } else if (IS_SCHEMA(child, "attributeGroup")) {
2958 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2959 child = child->next;
2960 } else if (IS_SCHEMA(child, "group")) {
2961 xmlSchemaParseGroup(ctxt, schema, child);
2962 child = child->next;
2963 } else if (IS_SCHEMA(child, "notation")) {
2964 xmlSchemaParseNotation(ctxt, schema, child);
2965 child = child->next;
2966 } else {
2967 xmlSchemaPErr2(ctxt, NULL, child,
2968 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
2969 "Schemas: unexpected element %s here \n",
2970 child->name, NULL);
2971 child = child->next;
2972 }
2973 while (IS_SCHEMA(child, "annotation")) {
2974 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2975 if (schema->annot == NULL)
2976 schema->annot = annot;
2977 else
2978 xmlSchemaFreeAnnot(annot);
2979 child = child->next;
2980 }
2981 }
2982}
2983
2984/**
2985 * xmlSchemaParseInclude:
2986 * @ctxt: a schema validation context
2987 * @schema: the schema being built
2988 * @node: a subtree containing XML Schema informations
2989 *
2990 * parse a XML schema Include definition
2991 *
2992 * Returns -1 in case of error, 0 if the declaration is inproper and
2993 * 1 in case of success.
2994 */
2995static int
2996xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2997 xmlNodePtr node)
2998{
2999 xmlNodePtr child = NULL;
3000 const xmlChar *schemaLocation;
3001 xmlURIPtr check;
3002 xmlDocPtr doc;
3003 xmlNodePtr root;
3004 xmlSchemaIncludePtr include;
3005
3006
3007 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3008 return (-1);
3009
3010 /*
3011 * Preliminary step, extract the URI-Reference for the include and
3012 * make an URI from the base.
3013 */
3014 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
3015 if (schemaLocation != NULL) {
3016 xmlChar *base = NULL;
3017 xmlChar *URI = NULL;
3018 check = xmlParseURI((const char *) schemaLocation);
3019 if (check == NULL) {
3020 xmlSchemaPErr2(ctxt, node, child,
3021 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3022 "Include schemaLocation attribute is not an URI: %s\n",
3023 schemaLocation, NULL);
3024 return (-1);
3025 } else {
3026 xmlFreeURI(check);
3027 }
3028 base = xmlNodeGetBase(node->doc, node);
3029 if (base == NULL) {
3030 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3031 } else {
3032 URI = xmlBuildURI(schemaLocation, base);
3033 xmlFree(base);
3034 }
3035 if (URI != NULL) {
3036 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3037 xmlFree(URI);
3038 }
3039 } else {
3040 xmlSchemaPErr2(ctxt, node, child,
3041 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3042 "Include schemaLocation attribute missing\n",
3043 NULL, NULL);
3044 return (-1);
3045 }
3046
3047 child = node->children;
3048 while (IS_SCHEMA(child, "annotation")) {
3049 /*
3050 * the annotations here are simply discarded ...
3051 */
3052 child = child->next;
3053 }
3054 if (child != NULL) {
3055 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3056 "Include has unexpected content\n", NULL, NULL);
3057 return (-1);
3058 }
3059
3060 /*
3061 * First step is to parse the input document into an DOM/Infoset
3062 */
3063 doc = xmlReadFile((const char *) schemaLocation, NULL,
3064 SCHEMAS_PARSE_OPTIONS);
3065 if (doc == NULL) {
3066 xmlSchemaPErr(ctxt, NULL,
3067 XML_SCHEMAP_FAILED_LOAD,
3068 "xmlSchemaParse: could not load %s\n",
3069 ctxt->URL, NULL);
3070 return(-1);
3071 }
3072
3073 /*
3074 * Then extract the root of the schema
3075 */
3076 root = xmlDocGetRootElement(doc);
3077 if (root == NULL) {
3078 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3079 XML_SCHEMAP_NOROOT,
3080 "schemas %s has no root", schemaLocation, NULL);
3081 xmlFreeDoc(doc);
3082 return (-1);
3083 }
3084
3085 /*
3086 * Remove all the blank text nodes
3087 */
3088 xmlSchemaCleanupDoc(ctxt, root);
3089
3090 /*
3091 * Check the schemas top level element
3092 */
3093 if (!IS_SCHEMA(root, "schema")) {
3094 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3095 XML_SCHEMAP_NOT_SCHEMA,
3096 "File %s is not a schemas", schemaLocation, NULL);
3097 xmlFreeDoc(doc);
3098 return (-1);
3099 }
3100
3101 /*
3102 * register the include
3103 */
3104 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3105 if (include == NULL) {
3106 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3107 xmlFreeDoc(doc);
3108 return (-1);
3109 }
3110
3111 memset(include, 0, sizeof(xmlSchemaInclude));
3112 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3113 include->doc = doc;
3114 include->next = schema->includes;
3115 schema->includes = include;
3116
3117
3118 /*
3119 * parse the declarations in the included file like if they
3120 * were in the original file.
3121 */
3122 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3123
3124 return (1);
3125}
3126
3127/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003128 * xmlSchemaParseChoice:
3129 * @ctxt: a schema validation context
3130 * @schema: the schema being built
3131 * @node: a subtree containing XML Schema informations
3132 *
3133 * parse a XML schema Choice definition
3134 * *WARNING* this interface is highly subject to change
3135 *
3136 * Returns -1 in case of error, 0 if the declaration is inproper and
3137 * 1 in case of success.
3138 */
3139static xmlSchemaTypePtr
3140xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003141 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003142{
3143 xmlSchemaTypePtr type, subtype, last = NULL;
3144 xmlNodePtr child = NULL;
3145 xmlChar name[30];
3146
3147 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3148 return (NULL);
3149
3150
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003151 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003152 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003153 if (type == NULL)
3154 return (NULL);
3155 type->node = node;
3156 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003157 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3159 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3160
3161 child = node->children;
3162 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003163 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3164 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003165 }
3166 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003167 (IS_SCHEMA(child, "group")) ||
3168 (IS_SCHEMA(child, "any")) ||
3169 (IS_SCHEMA(child, "choice")) ||
3170 (IS_SCHEMA(child, "sequence"))) {
3171 subtype = NULL;
3172 if (IS_SCHEMA(child, "element")) {
3173 subtype = (xmlSchemaTypePtr)
3174 xmlSchemaParseElement(ctxt, schema, child, 0);
3175 } else if (IS_SCHEMA(child, "group")) {
3176 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3177 } else if (IS_SCHEMA(child, "any")) {
3178 subtype = xmlSchemaParseAny(ctxt, schema, child);
3179 } else if (IS_SCHEMA(child, "sequence")) {
3180 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3181 } else if (IS_SCHEMA(child, "choice")) {
3182 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3183 }
3184 if (subtype != NULL) {
3185 if (last == NULL) {
3186 type->subtypes = subtype;
3187 last = subtype;
3188 } else {
3189 last->next = subtype;
3190 last = subtype;
3191 }
3192 last->next = NULL;
3193 }
3194 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003195 }
3196 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003197 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3198 "Choice %s has unexpected content\n", type->name,
3199 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 }
3201
3202 return (type);
3203}
3204
3205/**
3206 * xmlSchemaParseSequence:
3207 * @ctxt: a schema validation context
3208 * @schema: the schema being built
3209 * @node: a subtree containing XML Schema informations
3210 *
3211 * parse a XML schema Sequence definition
3212 * *WARNING* this interface is highly subject to change
3213 *
3214 * Returns -1 in case of error, 0 if the declaration is inproper and
3215 * 1 in case of success.
3216 */
3217static xmlSchemaTypePtr
3218xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003219 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003220{
3221 xmlSchemaTypePtr type, subtype, last = NULL;
3222 xmlNodePtr child = NULL;
3223 xmlChar name[30];
3224
3225 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3226 return (NULL);
3227
3228
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003229 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003230 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003231 if (type == NULL)
3232 return (NULL);
3233 type->node = node;
3234 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003235 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003236 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3237 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3238
3239 child = node->children;
3240 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003241 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3242 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003243 }
3244 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003245 (IS_SCHEMA(child, "group")) ||
3246 (IS_SCHEMA(child, "any")) ||
3247 (IS_SCHEMA(child, "choice")) ||
3248 (IS_SCHEMA(child, "sequence"))) {
3249 subtype = NULL;
3250 if (IS_SCHEMA(child, "element")) {
3251 subtype = (xmlSchemaTypePtr)
3252 xmlSchemaParseElement(ctxt, schema, child, 0);
3253 } else if (IS_SCHEMA(child, "group")) {
3254 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3255 } else if (IS_SCHEMA(child, "any")) {
3256 subtype = xmlSchemaParseAny(ctxt, schema, child);
3257 } else if (IS_SCHEMA(child, "choice")) {
3258 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3259 } else if (IS_SCHEMA(child, "sequence")) {
3260 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3261 }
3262 if (subtype != NULL) {
3263 if (last == NULL) {
3264 type->subtypes = subtype;
3265 last = subtype;
3266 } else {
3267 last->next = subtype;
3268 last = subtype;
3269 }
3270 last->next = NULL;
3271 }
3272 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003273 }
3274 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003275 xmlSchemaPErr2(ctxt, node, child,
3276 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3277 "Sequence %s has unexpected content\n", type->name,
3278 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003279 }
3280
3281 return (type);
3282}
3283
3284/**
3285 * xmlSchemaParseRestriction:
3286 * @ctxt: a schema validation context
3287 * @schema: the schema being built
3288 * @node: a subtree containing XML Schema informations
3289 * @simple: is that part of a simple type.
3290 *
3291 * parse a XML schema Restriction definition
3292 * *WARNING* this interface is highly subject to change
3293 *
3294 * Returns the type definition or NULL in case of error
3295 */
3296static xmlSchemaTypePtr
3297xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3298 xmlNodePtr node, int simple)
3299{
3300 xmlSchemaTypePtr type, subtype;
3301 xmlSchemaFacetPtr facet, lastfacet = NULL;
3302 xmlNodePtr child = NULL;
3303 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003304 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003305
3306 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3307 return (NULL);
3308
3309 oldcontainer = ctxt->container;
3310
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003311 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003312 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003313 if (type == NULL)
3314 return (NULL);
3315 type->node = node;
3316 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003317 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003318 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3319 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003320 xmlSchemaPErr2(ctxt, node, child,
3321 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3322 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003323 }
3324 ctxt->container = name;
3325
3326 child = node->children;
3327 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003328 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3329 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003330 }
3331 subtype = NULL;
3332
3333 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003334 subtype = (xmlSchemaTypePtr)
3335 xmlSchemaParseAll(ctxt, schema, child);
3336 child = child->next;
3337 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003338 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003339 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3340 child = child->next;
3341 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003342 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003343 subtype = (xmlSchemaTypePtr)
3344 xmlSchemaParseSequence(ctxt, schema, child);
3345 child = child->next;
3346 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003347 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003348 subtype = (xmlSchemaTypePtr)
3349 xmlSchemaParseGroup(ctxt, schema, child);
3350 child = child->next;
3351 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003352 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003353 if (IS_SCHEMA(child, "simpleType")) {
3354 subtype = (xmlSchemaTypePtr)
3355 xmlSchemaParseSimpleType(ctxt, schema, child);
3356 child = child->next;
3357 type->baseType = subtype;
3358 }
3359 /*
3360 * Facets
3361 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003362 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003363 (IS_SCHEMA(child, "minExclusive")) ||
3364 (IS_SCHEMA(child, "maxInclusive")) ||
3365 (IS_SCHEMA(child, "maxExclusive")) ||
3366 (IS_SCHEMA(child, "totalDigits")) ||
3367 (IS_SCHEMA(child, "fractionDigits")) ||
3368 (IS_SCHEMA(child, "pattern")) ||
3369 (IS_SCHEMA(child, "enumeration")) ||
3370 (IS_SCHEMA(child, "whiteSpace")) ||
3371 (IS_SCHEMA(child, "length")) ||
3372 (IS_SCHEMA(child, "maxLength")) ||
3373 (IS_SCHEMA(child, "minLength"))) {
3374 facet = xmlSchemaParseFacet(ctxt, schema, child);
3375 if (facet != NULL) {
3376 if (lastfacet == NULL) {
3377 type->facets = facet;
3378 lastfacet = facet;
3379 } else {
3380 lastfacet->next = facet;
3381 lastfacet = facet;
3382 }
3383 lastfacet->next = NULL;
3384 }
3385 child = child->next;
3386 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003387 }
3388 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3389 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003390 xmlSchemaPErr2(ctxt, node, child,
3391 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3392 "Restriction %s has unexpected content\n",
3393 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003394 }
3395 ctxt->container = oldcontainer;
3396 return (type);
3397}
3398
3399/**
3400 * xmlSchemaParseExtension:
3401 * @ctxt: a schema validation context
3402 * @schema: the schema being built
3403 * @node: a subtree containing XML Schema informations
3404 *
3405 * parse a XML schema Extension definition
3406 * *WARNING* this interface is highly subject to change
3407 *
3408 * Returns the type definition or NULL in case of error
3409 */
3410static xmlSchemaTypePtr
3411xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003413{
3414 xmlSchemaTypePtr type, subtype;
3415 xmlNodePtr child = NULL;
3416 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003417 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003418
3419 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3420 return (NULL);
3421
3422 oldcontainer = ctxt->container;
3423
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003424 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003425 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003426 if (type == NULL)
3427 return (NULL);
3428 type->node = node;
3429 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003430 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003431 ctxt->container = name;
3432
3433 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3434 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003435 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3436 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003437 }
3438 child = node->children;
3439 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003440 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3441 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003442 }
3443 subtype = NULL;
3444
3445 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003446 subtype = xmlSchemaParseAll(ctxt, schema, child);
3447 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003448 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003449 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3450 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003451 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003452 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3453 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003454 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003455 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3456 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003457 }
3458 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003459 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003460 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3461 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003462 xmlSchemaPErr2(ctxt, node, child,
3463 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3464 "Extension %s has unexpected content\n", type->name,
3465 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003466 }
3467 ctxt->container = oldcontainer;
3468 return (type);
3469}
3470
3471/**
3472 * xmlSchemaParseSimpleContent:
3473 * @ctxt: a schema validation context
3474 * @schema: the schema being built
3475 * @node: a subtree containing XML Schema informations
3476 *
3477 * parse a XML schema SimpleContent definition
3478 * *WARNING* this interface is highly subject to change
3479 *
3480 * Returns the type definition or NULL in case of error
3481 */
3482static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003483xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3484 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003485{
3486 xmlSchemaTypePtr type, subtype;
3487 xmlNodePtr child = NULL;
3488 xmlChar name[30];
3489
3490 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3491 return (NULL);
3492
3493
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003494 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003495 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003496 if (type == NULL)
3497 return (NULL);
3498 type->node = node;
3499 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003500 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003501
3502 child = node->children;
3503 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003504 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3505 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003506 }
3507 subtype = NULL;
3508 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003509 subtype = (xmlSchemaTypePtr)
3510 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3511 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003512 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003513 subtype = (xmlSchemaTypePtr)
3514 xmlSchemaParseExtension(ctxt, schema, child);
3515 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003516 }
3517 type->subtypes = subtype;
3518 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003519 xmlSchemaPErr2(ctxt, node, child,
3520 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3521 "SimpleContent %s has unexpected content\n",
3522 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003523 }
3524 return (type);
3525}
3526
3527/**
3528 * xmlSchemaParseComplexContent:
3529 * @ctxt: a schema validation context
3530 * @schema: the schema being built
3531 * @node: a subtree containing XML Schema informations
3532 *
3533 * parse a XML schema ComplexContent definition
3534 * *WARNING* this interface is highly subject to change
3535 *
3536 * Returns the type definition or NULL in case of error
3537 */
3538static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003539xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3540 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003541{
3542 xmlSchemaTypePtr type, subtype;
3543 xmlNodePtr child = NULL;
3544 xmlChar name[30];
3545
3546 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3547 return (NULL);
3548
3549
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003550 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003551 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003552 if (type == NULL)
3553 return (NULL);
3554 type->node = node;
3555 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003556 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003557
3558 child = node->children;
3559 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003560 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3561 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003562 }
3563 subtype = NULL;
3564 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003565 subtype = (xmlSchemaTypePtr)
3566 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3567 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003568 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003569 subtype = (xmlSchemaTypePtr)
3570 xmlSchemaParseExtension(ctxt, schema, child);
3571 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003572 }
3573 type->subtypes = subtype;
3574 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003575 xmlSchemaPErr2(ctxt, node, child,
3576 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3577 "ComplexContent %s has unexpected content\n",
3578 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003579 }
3580 return (type);
3581}
3582
3583/**
3584 * xmlSchemaParseComplexType:
3585 * @ctxt: a schema validation context
3586 * @schema: the schema being built
3587 * @node: a subtree containing XML Schema informations
3588 *
3589 * parse a XML schema Complex Type definition
3590 * *WARNING* this interface is highly subject to change
3591 *
3592 * Returns the type definition or NULL in case of error
3593 */
3594static xmlSchemaTypePtr
3595xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3596 xmlNodePtr node)
3597{
3598 xmlSchemaTypePtr type, subtype;
3599 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003600 const xmlChar *name;
3601 const xmlChar *oldcontainer;
Daniel Veillard1aefc862004-03-04 11:40:48 +00003602 const xmlChar *mixed;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003603 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003604
3605 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3606 return (NULL);
3607
3608 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003609 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003610 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003611
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003612 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3613 name = (const xmlChar *)buf;
3614 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3615 } else {
3616 const xmlChar *local, *ns;
3617
3618 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3619 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003622 return (NULL);
3623 }
Daniel Veillard1aefc862004-03-04 11:40:48 +00003624
3625 mixed = xmlSchemaGetProp(ctxt, node, "mixed");
3626 if (mixed != NULL)
3627 type->flags |= XML_SCHEMAS_TYPE_MIXED;
3628
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 type->node = node;
3630 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003631 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 ctxt->container = name;
3633
3634 child = node->children;
3635 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3637 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 }
3639 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003640 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003643 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3644 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003646 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003647
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 if (IS_SCHEMA(child, "all")) {
3649 subtype = xmlSchemaParseAll(ctxt, schema, child);
3650 child = child->next;
3651 } else if (IS_SCHEMA(child, "choice")) {
3652 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3653 child = child->next;
3654 } else if (IS_SCHEMA(child, "sequence")) {
3655 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3656 child = child->next;
3657 } else if (IS_SCHEMA(child, "group")) {
3658 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3659 child = child->next;
3660 }
3661 if (subtype != NULL)
3662 type->subtypes = subtype;
3663 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003664 }
3665 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003666 xmlSchemaPErr2(ctxt, node, child,
3667 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3668 "ComplexType %s has unexpected content\n",
3669 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 }
3671 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003672 return (type);
3673}
3674
Daniel Veillard4255d502002-04-16 15:50:10 +00003675/**
3676 * xmlSchemaParseSchema:
3677 * @ctxt: a schema validation context
3678 * @node: a subtree containing XML Schema informations
3679 *
3680 * parse a XML schema definition from a node set
3681 * *WARNING* this interface is highly subject to change
3682 *
3683 * Returns the internal XML Schema structure built from the resource or
3684 * NULL in case of error
3685 */
3686static xmlSchemaPtr
3687xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3688{
3689 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003690 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003691 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003692 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003693
3694 if ((ctxt == NULL) || (node == NULL))
3695 return (NULL);
3696
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003697 nberrors = ctxt->nberrors;
3698 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003699 if (IS_SCHEMA(node, "schema")) {
3700 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003701 if (schema == NULL)
3702 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003703 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3704 if (val != NULL) {
3705 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3706 } else {
3707 schema->targetNamespace = NULL;
3708 }
3709 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3710 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3711 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003712 if (val != NULL) {
3713 if (xmlStrEqual(val, BAD_CAST "qualified"))
3714 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3715 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3716 xmlSchemaPErr2(ctxt, node, child,
3717 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3718 "Invalid value %s for elementFormDefault\n",
3719 val, NULL);
3720 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003721 } else {
3722 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3723 }
3724 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003725 if (val != NULL) {
3726 if (xmlStrEqual(val, BAD_CAST "qualified"))
3727 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3728 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3729 xmlSchemaPErr2(ctxt, node, child,
3730 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3731 "Invalid value %s for attributeFormDefault\n",
3732 val, NULL);
3733 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003734 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003735
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003736 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
3737 } else {
3738 xmlDocPtr doc;
3739
3740 doc = node->doc;
3741
3742 if ((doc != NULL) && (doc->URL != NULL)) {
3743 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3744 XML_SCHEMAP_NOT_SCHEMA,
3745 "File %s is not a schemas", doc->URL, NULL);
3746 } else {
3747 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3748 XML_SCHEMAP_NOT_SCHEMA,
3749 "File is not a schemas", NULL, NULL);
3750 }
3751 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003752 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003753 if (ctxt->nberrors != 0) {
3754 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003755 xmlSchemaFree(schema);
3756 schema = NULL;
3757 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003758 }
3759 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003760#ifdef DEBUG
3761 if (schema == NULL)
3762 xmlGenericError(xmlGenericErrorContext,
3763 "xmlSchemaParse() failed\n");
3764#endif
3765
3766 return (schema);
3767}
3768
3769/************************************************************************
3770 * *
3771 * Validating using Schemas *
3772 * *
3773 ************************************************************************/
3774
3775/************************************************************************
3776 * *
3777 * Reading/Writing Schemas *
3778 * *
3779 ************************************************************************/
3780
3781/**
3782 * xmlSchemaNewParserCtxt:
3783 * @URL: the location of the schema
3784 *
3785 * Create an XML Schemas parse context for that file/resource expected
3786 * to contain an XML Schemas file.
3787 *
3788 * Returns the parser context or NULL in case of error
3789 */
3790xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003791xmlSchemaNewParserCtxt(const char *URL)
3792{
Daniel Veillard4255d502002-04-16 15:50:10 +00003793 xmlSchemaParserCtxtPtr ret;
3794
3795 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003796 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003797
3798 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3799 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003800 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3801 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003802 return (NULL);
3803 }
3804 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003805 ret->dict = xmlDictCreate();
3806 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003807 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003808 return (ret);
3809}
3810
3811/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003812 * xmlSchemaNewMemParserCtxt:
3813 * @buffer: a pointer to a char array containing the schemas
3814 * @size: the size of the array
3815 *
3816 * Create an XML Schemas parse context for that memory buffer expected
3817 * to contain an XML Schemas file.
3818 *
3819 * Returns the parser context or NULL in case of error
3820 */
3821xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003822xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3823{
Daniel Veillard6045c902002-10-09 21:13:59 +00003824 xmlSchemaParserCtxtPtr ret;
3825
3826 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003827 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003828
3829 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3830 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003831 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3832 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003833 return (NULL);
3834 }
3835 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3836 ret->buffer = buffer;
3837 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003838 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00003839 return (ret);
3840}
3841
3842/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003843 * xmlSchemaNewDocParserCtxt:
3844 * @doc: a preparsed document tree
3845 *
3846 * Create an XML Schemas parse context for that document.
3847 * NB. The document may be modified during the parsing process.
3848 *
3849 * Returns the parser context or NULL in case of error
3850 */
3851xmlSchemaParserCtxtPtr
3852xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3853{
3854 xmlSchemaParserCtxtPtr ret;
3855
3856 if (doc == NULL)
3857 return (NULL);
3858
3859 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3860 if (ret == NULL) {
3861 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3862 NULL);
3863 return (NULL);
3864 }
3865 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3866 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003867 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00003868 /* The application has responsibility for the document */
3869 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00003870
3871 return (ret);
3872}
3873
3874/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003875 * xmlSchemaFreeParserCtxt:
3876 * @ctxt: the schema parser context
3877 *
3878 * Free the resources associated to the schema parser context
3879 */
3880void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003881xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3882{
Daniel Veillard4255d502002-04-16 15:50:10 +00003883 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003884 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00003885 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003886 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003887 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003888 xmlFree(ctxt);
3889}
3890
3891/************************************************************************
3892 * *
3893 * Building the content models *
3894 * *
3895 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003896
Daniel Veillard4255d502002-04-16 15:50:10 +00003897/**
3898 * xmlSchemaBuildAContentModel:
3899 * @type: the schema type definition
3900 * @ctxt: the schema parser context
3901 * @name: the element name whose content is being built
3902 *
3903 * Generate the automata sequence needed for that type
3904 */
3905static void
3906xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003907 xmlSchemaParserCtxtPtr ctxt,
3908 const xmlChar * name)
3909{
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 xmlGenericError(xmlGenericErrorContext,
3912 "Found unexpected type = NULL in %s content model\n",
3913 name);
3914 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003915 }
3916 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003917 case XML_SCHEMA_TYPE_ANY:
3918 /* TODO : handle the namespace too */
3919 /* TODO : make that a specific transition type */
3920 TODO ctxt->state =
3921 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3922 BAD_CAST "*", NULL);
3923 break;
3924 case XML_SCHEMA_TYPE_ELEMENT:{
3925 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003926
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003927 /* TODO : handle the namespace too */
3928 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003929
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003930 if (elem->maxOccurs >= UNBOUNDED) {
3931 if (elem->minOccurs > 1) {
3932 xmlAutomataStatePtr tmp;
3933 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003934
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003935 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3936 oldstate,
3937 NULL);
3938 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003939
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003940 counter = xmlAutomataNewCounter(ctxt->am,
3941 elem->minOccurs -
3942 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003943
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003944 if (elem->refDecl != NULL) {
3945 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3946 elem->refDecl,
3947 ctxt,
3948 elem->refDecl->
3949 name);
3950 } else {
3951 ctxt->state =
3952 xmlAutomataNewTransition(ctxt->am,
3953 ctxt->state, NULL,
3954 elem->name, type);
3955 }
3956 tmp = ctxt->state;
3957 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3958 counter);
3959 ctxt->state =
3960 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3961 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003962
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003963 } else {
3964 if (elem->refDecl != NULL) {
3965 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3966 elem->refDecl,
3967 ctxt,
3968 elem->refDecl->
3969 name);
3970 } else {
3971 ctxt->state =
3972 xmlAutomataNewTransition(ctxt->am,
3973 ctxt->state, NULL,
3974 elem->name, type);
3975 }
3976 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3977 oldstate);
3978 if (elem->minOccurs == 0) {
3979 /* basically an elem* */
3980 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3981 ctxt->state);
3982 }
3983 }
3984 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3985 xmlAutomataStatePtr tmp;
3986 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003987
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003988 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3989 oldstate, NULL);
3990 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003991
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003992 counter = xmlAutomataNewCounter(ctxt->am,
3993 elem->minOccurs - 1,
3994 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003995
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003996 if (elem->refDecl != NULL) {
3997 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3998 elem->refDecl, ctxt,
3999 elem->refDecl->name);
4000 } else {
4001 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4002 ctxt->state,
4003 NULL,
4004 elem->name,
4005 type);
4006 }
4007 tmp = ctxt->state;
4008 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4009 counter);
4010 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
4011 NULL,
4012 counter);
4013 if (elem->minOccurs == 0) {
4014 /* basically an elem? */
4015 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4016 ctxt->state);
4017 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004018
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019 } else {
4020 if (elem->refDecl != NULL) {
4021 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4022 elem->refDecl, ctxt,
4023 elem->refDecl->name);
4024 } else {
4025 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4026 ctxt->state,
4027 NULL,
4028 elem->name,
4029 type);
4030 }
4031 if (elem->minOccurs == 0) {
4032 /* basically an elem? */
4033 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4034 ctxt->state);
4035 }
4036 }
4037 break;
4038 }
4039 case XML_SCHEMA_TYPE_SEQUENCE:{
4040 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004041
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004042 /*
4043 * If max and min occurances are default (1) then
4044 * simply iterate over the subtypes
4045 */
4046 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4047 subtypes = type->subtypes;
4048 while (subtypes != NULL) {
4049 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4050 subtypes = subtypes->next;
4051 }
4052 } else {
4053 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004054
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004055 if (type->maxOccurs >= UNBOUNDED) {
4056 if (type->minOccurs > 1) {
4057 xmlAutomataStatePtr tmp;
4058 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004059
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004060 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4061 oldstate,
4062 NULL);
4063 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004064
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004065 counter = xmlAutomataNewCounter(ctxt->am,
4066 type->
4067 minOccurs - 1,
4068 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004069
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004070 subtypes = type->subtypes;
4071 while (subtypes != NULL) {
4072 xmlSchemaBuildAContentModel(subtypes, ctxt,
4073 name);
4074 subtypes = subtypes->next;
4075 }
4076 tmp = ctxt->state;
4077 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4078 oldstate, counter);
4079 ctxt->state =
4080 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4081 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004082
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004083 } else {
4084 subtypes = type->subtypes;
4085 while (subtypes != NULL) {
4086 xmlSchemaBuildAContentModel(subtypes, ctxt,
4087 name);
4088 subtypes = subtypes->next;
4089 }
4090 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4091 oldstate);
4092 if (type->minOccurs == 0) {
4093 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4094 ctxt->state);
4095 }
4096 }
4097 } else if ((type->maxOccurs > 1)
4098 || (type->minOccurs > 1)) {
4099 xmlAutomataStatePtr tmp;
4100 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004101
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004102 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4103 oldstate,
4104 NULL);
4105 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004106
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004107 counter = xmlAutomataNewCounter(ctxt->am,
4108 type->minOccurs -
4109 1,
4110 type->maxOccurs -
4111 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004112
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004113 subtypes = type->subtypes;
4114 while (subtypes != NULL) {
4115 xmlSchemaBuildAContentModel(subtypes, ctxt,
4116 name);
4117 subtypes = subtypes->next;
4118 }
4119 tmp = ctxt->state;
4120 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4121 counter);
4122 ctxt->state =
4123 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4124 counter);
4125 if (type->minOccurs == 0) {
4126 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4127 ctxt->state);
4128 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004129
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004130 } else {
4131 subtypes = type->subtypes;
4132 while (subtypes != NULL) {
4133 xmlSchemaBuildAContentModel(subtypes, ctxt,
4134 name);
4135 subtypes = subtypes->next;
4136 }
4137 if (type->minOccurs == 0) {
4138 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4139 ctxt->state);
4140 }
4141 }
4142 }
4143 break;
4144 }
4145 case XML_SCHEMA_TYPE_CHOICE:{
4146 xmlSchemaTypePtr subtypes;
4147 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004148
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004149 start = ctxt->state;
4150 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004151
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004152 /*
4153 * iterate over the subtypes and remerge the end with an
4154 * epsilon transition
4155 */
4156 if (type->maxOccurs == 1) {
4157 subtypes = type->subtypes;
4158 while (subtypes != NULL) {
4159 ctxt->state = start;
4160 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4161 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4162 subtypes = subtypes->next;
4163 }
4164 } else {
4165 int counter;
4166 xmlAutomataStatePtr hop;
4167 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4168 UNBOUNDED : type->maxOccurs - 1;
4169 int minOccurs =
4170 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004171
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 /*
4173 * use a counter to keep track of the number of transtions
4174 * which went through the choice.
4175 */
4176 counter =
4177 xmlAutomataNewCounter(ctxt->am, minOccurs,
4178 maxOccurs);
4179 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004180
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004181 subtypes = type->subtypes;
4182 while (subtypes != NULL) {
4183 ctxt->state = start;
4184 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4185 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4186 subtypes = subtypes->next;
4187 }
4188 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4189 counter);
4190 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4191 counter);
4192 }
4193 if (type->minOccurs == 0) {
4194 xmlAutomataNewEpsilon(ctxt->am, start, end);
4195 }
4196 ctxt->state = end;
4197 break;
4198 }
4199 case XML_SCHEMA_TYPE_ALL:{
4200 xmlAutomataStatePtr start;
4201 xmlSchemaTypePtr subtypes;
4202 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4203 int lax;
4204
4205 subtypes = type->subtypes;
4206 if (subtypes == NULL)
4207 break;
4208 start = ctxt->state;
4209 while (subtypes != NULL) {
4210 ctxt->state = start;
4211 elem = (xmlSchemaElementPtr) subtypes;
4212
4213 /* TODO : handle the namespace too */
4214 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4215 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4216 ctxt->state, elem->name, 1,
4217 1, subtypes);
4218 } else {
4219 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4220 ctxt->state, elem->name,
4221 elem->minOccurs,
4222 elem->maxOccurs,
4223 subtypes);
4224 }
4225 subtypes = subtypes->next;
4226 }
4227 lax = type->minOccurs == 0;
4228 ctxt->state =
4229 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4230 lax);
4231 break;
4232 }
4233 case XML_SCHEMA_TYPE_RESTRICTION:
4234 if (type->subtypes != NULL)
4235 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4236 break;
4237 case XML_SCHEMA_TYPE_EXTENSION:
4238 if (type->baseType != NULL) {
4239 xmlSchemaTypePtr subtypes;
4240
4241 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4242 subtypes = type->subtypes;
4243 while (subtypes != NULL) {
4244 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4245 subtypes = subtypes->next;
4246 }
4247 } else if (type->subtypes != NULL)
4248 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4249 break;
4250 case XML_SCHEMA_TYPE_GROUP:
4251 if (type->subtypes == NULL) {
4252 }
4253 case XML_SCHEMA_TYPE_COMPLEX:
4254 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4255 if (type->subtypes != NULL)
4256 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4257 break;
4258 default:
4259 xmlGenericError(xmlGenericErrorContext,
4260 "Found unexpected type %d in %s content model\n",
4261 type->type, name);
4262 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 }
4264}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004265
Daniel Veillard4255d502002-04-16 15:50:10 +00004266/**
4267 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004268 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004270 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004271 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004272 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004273 */
4274static void
4275xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004276 xmlSchemaParserCtxtPtr ctxt,
4277 const xmlChar * name)
4278{
Daniel Veillard4255d502002-04-16 15:50:10 +00004279 xmlAutomataStatePtr start;
4280
Daniel Veillard4255d502002-04-16 15:50:10 +00004281 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004282 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004283 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004284 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4285 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004286 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004288 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004289 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4290 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004291 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004292
4293#ifdef DEBUG_CONTENT
4294 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004295 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004296#endif
4297
Daniel Veillard4255d502002-04-16 15:50:10 +00004298 ctxt->am = xmlNewAutomata();
4299 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004300 xmlGenericError(xmlGenericErrorContext,
4301 "Cannot create automata for elem %s\n", name);
4302 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 }
4304 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4305 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4306 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004307 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004308 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4310 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004311 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4313 "Content model of %s is not determinist:\n", name,
4314 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004315 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004316#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 xmlGenericError(xmlGenericErrorContext,
4318 "Content model of %s:\n", name);
4319 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004320#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004321 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004322 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004323 xmlFreeAutomata(ctxt->am);
4324 ctxt->am = NULL;
4325}
4326
4327/**
4328 * xmlSchemaRefFixupCallback:
4329 * @elem: the schema element context
4330 * @ctxt: the schema parser context
4331 *
4332 * Free the resources associated to the schema parser context
4333 */
4334static void
4335xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004336 xmlSchemaParserCtxtPtr ctxt,
4337 const xmlChar * name,
4338 const xmlChar * context ATTRIBUTE_UNUSED,
4339 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004340{
4341 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004342 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004343 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004344 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004345
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004346 if (elem->subtypes != NULL) {
4347 xmlSchemaPErr(ctxt, elem->node,
4348 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4349 "Schemas: element %s have both ref and subtype\n",
4350 name, NULL);
4351 return;
4352 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004353 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004354
4355 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004356 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4357 "Schemas: element %s ref to %s not found\n",
4358 name, elem->ref);
4359 return;
4360 }
4361 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004363 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004364
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004365 if (elem->subtypes != NULL) {
4366 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4367 "Schemas: element %s have both type and subtype\n",
4368 name, NULL);
4369 return;
4370 }
4371 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4372 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004373
4374 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004375 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4376 "Schemas: element %s type %s not found\n", name,
4377 elem->namedType);
4378 return;
4379 }
4380 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 }
4382}
4383
Daniel Veillard377e1a92004-04-16 16:30:05 +00004384static void
4385xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr typeDecl,
4386 xmlSchemaParserCtxtPtr ctxt)
4387{
4388 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
4389 xmlChar *tmp;
4390 xmlSchemaTypePtr subtype;
4391 xmlNsPtr ns;
4392 int len;
4393
4394 if ((typeDecl->type != XML_SCHEMA_TYPE_UNION) || (typeDecl->ref == NULL))
4395 return;
4396
4397 cur = typeDecl->ref;
4398 do {
4399 while (IS_BLANK_CH(*cur))
4400 cur++;
4401 end = cur;
4402 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4403 end++;
4404 if (end == cur)
4405 break;
4406 tmp = xmlStrndup(cur, end - cur);
4407 ncName = xmlSplitQName3(tmp, &len);
4408 if (ncName != NULL) {
4409 prefix = xmlDictLookup(ctxt->dict, tmp, len);
4410 } else {
4411 prefix = NULL;
4412 ncName = tmp;
4413 }
4414 ns = xmlSearchNs(typeDecl->node->doc, typeDecl->node, prefix);
4415 if (ns == NULL) {
4416 xmlSchemaPErr(ctxt, typeDecl->node, XML_SCHEMAP_PREFIX_UNDEFINED,
4417 "Union %s: the namespace of member type %s is undefined\n",
William M. Brack87640d52004-04-17 14:58:15 +00004418 typeDecl->name, (const xmlChar *) tmp);
4419 namespace = NULL;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004420 } else {
4421 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4422 }
4423 /* Lookup the referenced type */
4424 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
4425 if (subtype == NULL) {
4426 xmlSchemaPErr(ctxt, typeDecl->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
4427 "Union %s references an unknown member type >%s<\n",
William M. Brack87640d52004-04-17 14:58:15 +00004428 typeDecl->name, (const xmlChar *) tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004429 }
4430 xmlFree(tmp);
4431 cur = end;
4432 } while (*cur != 0);
4433
4434}
4435
Daniel Veillard4255d502002-04-16 15:50:10 +00004436/**
4437 * xmlSchemaTypeFixup:
4438 * @typeDecl: the schema type definition
4439 * @ctxt: the schema parser context
4440 *
4441 * Fixes the content model of the type.
4442 */
4443static void
4444xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004445 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004446{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004447 if (typeDecl == NULL)
4448 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004450 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004451 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004452 switch (typeDecl->type) {
4453 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4454 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4455 if (typeDecl->subtypes != NULL)
4456 typeDecl->contentType =
4457 typeDecl->subtypes->contentType;
4458 break;
4459 }
4460 case XML_SCHEMA_TYPE_RESTRICTION:{
4461 if (typeDecl->subtypes != NULL)
4462 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004463
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004464 if (typeDecl->base != NULL) {
4465 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004466
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004467 baseType =
4468 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4469 typeDecl->baseNs);
4470 if (baseType == NULL) {
4471 xmlSchemaPErr(ctxt, typeDecl->node,
4472 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004473 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004474 name, typeDecl->base);
4475 }
4476 typeDecl->baseType = baseType;
4477 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004478 if (typeDecl->subtypes == NULL)
4479 if (typeDecl->baseType != NULL)
4480 typeDecl->contentType =
4481 typeDecl->baseType->contentType;
4482 else
4483 /* 1.1.1 */
4484 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004485 else if ((typeDecl->subtypes->subtypes == NULL) &&
4486 ((typeDecl->subtypes->type ==
4487 XML_SCHEMA_TYPE_ALL)
4488 || (typeDecl->subtypes->type ==
4489 XML_SCHEMA_TYPE_SEQUENCE)))
4490 /* 1.1.2 */
4491 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4492 else if ((typeDecl->subtypes->type ==
4493 XML_SCHEMA_TYPE_CHOICE)
4494 && (typeDecl->subtypes->subtypes == NULL))
4495 /* 1.1.3 */
4496 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4497 else {
4498 /* 1.2 and 2.X are applied at the other layer */
4499 typeDecl->contentType =
4500 XML_SCHEMA_CONTENT_ELEMENTS;
4501 }
4502 break;
4503 }
4504 case XML_SCHEMA_TYPE_EXTENSION:{
4505 xmlSchemaContentType explicitContentType;
4506 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004507
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004508 if (typeDecl->base != NULL) {
4509 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004510
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004511 baseType =
4512 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4513 typeDecl->baseNs);
4514 if (baseType == NULL) {
4515 xmlSchemaPErr(ctxt, typeDecl->node,
4516 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004517 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004518 name, typeDecl->base);
4519 }
4520 typeDecl->baseType = baseType;
4521 }
4522 if (typeDecl->subtypes != NULL)
4523 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004524
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004525 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4526 if (typeDecl->subtypes == NULL)
4527 /* 1.1.1 */
4528 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4529 else if ((typeDecl->subtypes->subtypes == NULL) &&
4530 ((typeDecl->subtypes->type ==
4531 XML_SCHEMA_TYPE_ALL)
4532 || (typeDecl->subtypes->type ==
4533 XML_SCHEMA_TYPE_SEQUENCE)))
4534 /* 1.1.2 */
4535 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4536 else if ((typeDecl->subtypes->type ==
4537 XML_SCHEMA_TYPE_CHOICE)
4538 && (typeDecl->subtypes->subtypes == NULL))
4539 /* 1.1.3 */
4540 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004541
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004542 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4543 typeDecl->baseNs);
4544 if (base == NULL) {
4545 xmlSchemaPErr(ctxt, typeDecl->node,
4546 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4547 "Schemas: base type %s of type %s not found\n",
4548 typeDecl->base, name);
4549 return;
4550 }
4551 xmlSchemaTypeFixup(base, ctxt, NULL);
4552 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4553 /* 2.1 */
4554 typeDecl->contentType = base->contentType;
4555 } else if (base->contentType ==
4556 XML_SCHEMA_CONTENT_EMPTY) {
4557 /* 2.2 imbitable ! */
4558 typeDecl->contentType =
4559 XML_SCHEMA_CONTENT_ELEMENTS;
4560 } else {
4561 /* 2.3 imbitable pareil ! */
4562 typeDecl->contentType =
4563 XML_SCHEMA_CONTENT_ELEMENTS;
4564 }
4565 break;
4566 }
4567 case XML_SCHEMA_TYPE_COMPLEX:{
4568 if (typeDecl->subtypes == NULL) {
4569 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004570
4571 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4572 typeDecl->contentType =
4573 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004574 } else {
4575 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4576 typeDecl->contentType =
4577 XML_SCHEMA_CONTENT_MIXED;
4578 else {
4579 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4580 NULL);
4581 if (typeDecl->subtypes != NULL)
4582 typeDecl->contentType =
4583 typeDecl->subtypes->contentType;
4584 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004585 if (typeDecl->attributes == NULL)
4586 typeDecl->attributes =
4587 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004588 }
4589 break;
4590 }
4591 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4592 if (typeDecl->subtypes == NULL) {
4593 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004594 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4595 typeDecl->contentType =
4596 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004597 } else {
4598 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4599 typeDecl->contentType =
4600 XML_SCHEMA_CONTENT_MIXED;
4601 else {
4602 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4603 NULL);
4604 if (typeDecl->subtypes != NULL)
4605 typeDecl->contentType =
4606 typeDecl->subtypes->contentType;
4607 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004608 if (typeDecl->attributes == NULL)
4609 typeDecl->attributes =
4610 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004611 }
4612 break;
4613 }
4614 case XML_SCHEMA_TYPE_SEQUENCE:
4615 case XML_SCHEMA_TYPE_GROUP:
4616 case XML_SCHEMA_TYPE_ALL:
4617 case XML_SCHEMA_TYPE_CHOICE:
4618 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4619 break;
4620 case XML_SCHEMA_TYPE_BASIC:
4621 case XML_SCHEMA_TYPE_ANY:
4622 case XML_SCHEMA_TYPE_FACET:
4623 case XML_SCHEMA_TYPE_SIMPLE:
4624 case XML_SCHEMA_TYPE_UR:
4625 case XML_SCHEMA_TYPE_ELEMENT:
4626 case XML_SCHEMA_TYPE_ATTRIBUTE:
4627 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4628 case XML_SCHEMA_TYPE_NOTATION:
4629 case XML_SCHEMA_TYPE_LIST:
4630 case XML_SCHEMA_TYPE_UNION:
Daniel Veillard377e1a92004-04-16 16:30:05 +00004631 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004632 case XML_SCHEMA_FACET_MININCLUSIVE:
4633 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4634 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4635 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4636 case XML_SCHEMA_FACET_TOTALDIGITS:
4637 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4638 case XML_SCHEMA_FACET_PATTERN:
4639 case XML_SCHEMA_FACET_ENUMERATION:
4640 case XML_SCHEMA_FACET_WHITESPACE:
4641 case XML_SCHEMA_FACET_LENGTH:
4642 case XML_SCHEMA_FACET_MAXLENGTH:
4643 case XML_SCHEMA_FACET_MINLENGTH:
4644 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004645 if (typeDecl->subtypes != NULL)
4646 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004647 break;
4648 }
4649 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004650#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004651 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004652 xmlGenericError(xmlGenericErrorContext,
4653 "Type of %s : %s:%d :", name,
4654 typeDecl->node->doc->URL,
4655 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004656 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004657 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004658 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004659 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004660 case XML_SCHEMA_CONTENT_SIMPLE:
4661 xmlGenericError(xmlGenericErrorContext, "simple\n");
4662 break;
4663 case XML_SCHEMA_CONTENT_ELEMENTS:
4664 xmlGenericError(xmlGenericErrorContext, "elements\n");
4665 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004666 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004667 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4668 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004669 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004670 xmlGenericError(xmlGenericErrorContext, "empty\n");
4671 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004672 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004673 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4674 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004675 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004676 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4677 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004678 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004679 xmlGenericError(xmlGenericErrorContext, "basic\n");
4680 break;
4681 default:
4682 xmlGenericError(xmlGenericErrorContext,
4683 "not registered !!!\n");
4684 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004685 }
4686#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004687}
4688
4689/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004690 * xmlSchemaCheckFacet:
4691 * @facet: the facet
4692 * @typeDecl: the schema type definition
4693 * @ctxt: the schema parser context or NULL
4694 * @name: name of the type
4695 *
4696 * Checks the default values types, especially for facets
4697 *
4698 * Returns 0 if okay or -1 in cae of error
4699 */
4700int
4701xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004702 xmlSchemaTypePtr typeDecl,
4703 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004704{
4705 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4706 int ret = 0;
4707
4708 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004709 nonNegativeIntegerType =
4710 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4711 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004712 }
4713 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004714 case XML_SCHEMA_FACET_MININCLUSIVE:
4715 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4716 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4717 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4718 /*
4719 * Okay we need to validate the value
4720 * at that point.
4721 */
4722 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004723
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004724 vctxt = xmlSchemaNewValidCtxt(NULL);
4725 if (vctxt == NULL)
4726 break;
4727 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4728 facet->value);
4729 facet->val = vctxt->value;
4730 vctxt->value = NULL;
4731 if (facet->val == NULL) {
4732 /* error code */
4733 if (ctxt != NULL) {
4734 xmlSchemaPErr(ctxt, facet->node,
4735 XML_SCHEMAP_INVALID_FACET,
4736 "Schemas: type %s facet value %s invalid\n",
4737 name, facet->value);
4738 }
4739 ret = -1;
4740 }
4741 xmlSchemaFreeValidCtxt(vctxt);
4742 break;
4743 }
4744 case XML_SCHEMA_FACET_ENUMERATION:{
4745 /*
4746 * Okay we need to validate the value
4747 * at that point.
4748 */
4749 xmlSchemaValidCtxtPtr vctxt;
4750 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004751
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004752 vctxt = xmlSchemaNewValidCtxt(NULL);
4753 if (vctxt == NULL)
4754 break;
4755 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4756 facet->value);
4757 if (tmp != 0) {
4758 if (ctxt != NULL) {
4759 xmlSchemaPErr(ctxt, facet->node,
4760 XML_SCHEMAP_INVALID_ENUM,
4761 "Schemas: type %s enumeration value %s invalid\n",
4762 name, facet->value);
4763 }
4764 ret = -1;
4765 }
4766 xmlSchemaFreeValidCtxt(vctxt);
4767 break;
4768 }
4769 case XML_SCHEMA_FACET_PATTERN:
4770 facet->regexp = xmlRegexpCompile(facet->value);
4771 if (facet->regexp == NULL) {
4772 xmlSchemaPErr(ctxt, typeDecl->node,
4773 XML_SCHEMAP_REGEXP_INVALID,
4774 "Schemas: type %s facet regexp %s invalid\n",
4775 name, facet->value);
4776 ret = -1;
4777 }
4778 break;
4779 case XML_SCHEMA_FACET_TOTALDIGITS:
4780 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4781 case XML_SCHEMA_FACET_LENGTH:
4782 case XML_SCHEMA_FACET_MAXLENGTH:
4783 case XML_SCHEMA_FACET_MINLENGTH:{
4784 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004785
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004786 tmp =
4787 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4788 facet->value,
4789 &facet->val);
4790 if (tmp != 0) {
4791 /* error code */
4792 if (ctxt != NULL) {
4793 xmlSchemaPErr(ctxt, facet->node,
4794 XML_SCHEMAP_INVALID_FACET_VALUE,
4795 "Schemas: type %s facet value %s invalid\n",
4796 name, facet->value);
4797 }
4798 ret = -1;
4799 }
4800 break;
4801 }
4802 case XML_SCHEMA_FACET_WHITESPACE:{
4803 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4804 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4805 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4806 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4807 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4808 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4809 } else {
4810 if (ctxt != NULL) {
4811 xmlSchemaPErr(ctxt, facet->node,
4812 XML_SCHEMAP_INVALID_WHITE_SPACE,
4813 "Schemas: type %s whiteSpace value %s invalid\n",
4814 name, facet->value);
4815 }
4816 ret = -1;
4817 }
4818 }
4819 default:
4820 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004821 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004822 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004823}
4824
4825/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004826 * xmlSchemaCheckDefaults:
4827 * @typeDecl: the schema type definition
4828 * @ctxt: the schema parser context
4829 *
4830 * Checks the default values types, especially for facets
4831 */
4832static void
4833xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004834 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004835{
Daniel Veillard4255d502002-04-16 15:50:10 +00004836 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004837 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004838 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004839 if (typeDecl->facets != NULL) {
4840 xmlSchemaFacetPtr facet = typeDecl->facets;
4841
4842 while (facet != NULL) {
4843 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4844 facet = facet->next;
4845 }
4846 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004847 }
4848}
4849
4850/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004851 * xmlSchemaAttrGrpFixup:
4852 * @attrgrpDecl: the schema attribute definition
4853 * @ctxt: the schema parser context
4854 * @name: the attribute name
4855 *
4856 * Fixes finish doing the computations on the attributes definitions
4857 */
4858static void
4859xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004860 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004861{
4862 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004863 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004864 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004865 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004866 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004867 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004868
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004869 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4870 attrgrpDecl->refNs);
4871 if (ref == NULL) {
4872 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4873 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4874 "Schemas: attribute group %s reference %s not found\n",
4875 name, attrgrpDecl->ref);
4876 return;
4877 }
4878 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4879 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004880 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004881 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4882 "Schemas: attribute %s has no attributes nor reference\n",
4883 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004884 }
4885}
4886
4887/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004888 * xmlSchemaAttrFixup:
4889 * @attrDecl: the schema attribute definition
4890 * @ctxt: the schema parser context
4891 * @name: the attribute name
4892 *
4893 * Fixes finish doing the computations on the attributes definitions
4894 */
4895static void
4896xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004897 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004898{
4899 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004900 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004901 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004902 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004903 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004905
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004906 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4907 attrDecl->typeNs);
4908 if (type == NULL) {
4909 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4910 "Schemas: attribute %s type %s not found\n",
4911 name, attrDecl->typeName);
4912 }
4913 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004914 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004916
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004917 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4918 attrDecl->refNs);
4919 if (ref == NULL) {
4920 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4921 "Schemas: attribute %s reference %s not found\n",
4922 name, attrDecl->ref);
4923 return;
4924 }
4925 xmlSchemaAttrFixup(ref, ctxt, NULL);
4926 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004927 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004928 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4929 "Schemas: attribute %s has no type nor reference\n",
4930 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004931 }
4932}
4933
4934/**
4935 * xmlSchemaParse:
4936 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004937 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004938 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004939 * XML Shema struture which can be used to validate instances.
4940 * *WARNING* this interface is highly subject to change
4941 *
4942 * Returns the internal XML Schema structure built from the resource or
4943 * NULL in case of error
4944 */
4945xmlSchemaPtr
4946xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4947{
4948 xmlSchemaPtr ret = NULL;
4949 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004950 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004951 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004952 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004953
4954 xmlSchemaInitTypes();
4955
Daniel Veillard6045c902002-10-09 21:13:59 +00004956 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004957 return (NULL);
4958
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004959 nberrors = ctxt->nberrors;
4960 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004961 ctxt->counter = 0;
4962 ctxt->container = NULL;
4963
4964 /*
4965 * First step is to parse the input document into an DOM/Infoset
4966 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004967 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004968 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4969 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004970 if (doc == NULL) {
4971 xmlSchemaPErr(ctxt, NULL,
4972 XML_SCHEMAP_FAILED_LOAD,
4973 "xmlSchemaParse: could not load %s\n",
4974 ctxt->URL, NULL);
4975 return (NULL);
4976 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004977 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004978 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4979 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004980 if (doc == NULL) {
4981 xmlSchemaPErr(ctxt, NULL,
4982 XML_SCHEMAP_FAILED_PARSE,
4983 "xmlSchemaParse: could not parse\n",
4984 NULL, NULL);
4985 return (NULL);
4986 }
4987 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00004988 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00004989 } else if (ctxt->doc != NULL) {
4990 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004991 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00004992 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004993 xmlSchemaPErr(ctxt, NULL,
4994 XML_SCHEMAP_NOTHING_TO_PARSE,
4995 "xmlSchemaParse: could not parse\n",
4996 NULL, NULL);
4997 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004998 }
4999
5000 /*
5001 * Then extract the root and Schema parse it
5002 */
5003 root = xmlDocGetRootElement(doc);
5004 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005005 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5006 XML_SCHEMAP_NOROOT,
5007 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00005008 if (!preserve) {
5009 xmlFreeDoc(doc);
5010 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005011 return (NULL);
5012 }
5013
5014 /*
5015 * Remove all the blank text nodes
5016 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005017 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00005018
5019 /*
5020 * Then do the parsing for good
5021 */
5022 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00005023 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00005024 if (!preserve) {
5025 xmlFreeDoc(doc);
5026 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005027 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00005028 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005029 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005030 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00005031
5032 /*
5033 * Then fix all the references.
5034 */
5035 ctxt->schema = ret;
5036 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005037 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005038
5039 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005040 * Then fixup all attributes declarations
5041 */
5042 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5043
5044 /*
5045 * Then fixup all attributes group declarations
5046 */
5047 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5048 ctxt);
5049
5050 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00005051 * Then fixup all types properties
5052 */
5053 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5054
5055 /*
5056 * Then build the content model for all elements
5057 */
5058 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005059 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005060
5061 /*
5062 * Then check the defaults part of the type like facets values
5063 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005064 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5065 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005066
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005067 if (ctxt->nberrors != 0) {
5068 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005069 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005070 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005071 return (ret);
5072}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005073
Daniel Veillard4255d502002-04-16 15:50:10 +00005074/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00005075 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005076 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005077 * @err: the error callback
5078 * @warn: the warning callback
5079 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005081 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005082 */
5083void
5084xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005085 xmlSchemaValidityErrorFunc err,
5086 xmlSchemaValidityWarningFunc warn, void *ctx)
5087{
Daniel Veillard4255d502002-04-16 15:50:10 +00005088 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005089 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005090 ctxt->error = err;
5091 ctxt->warning = warn;
5092 ctxt->userData = ctx;
5093}
5094
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005095/**
5096 * xmlSchemaFacetTypeToString:
5097 * @type: the facet type
5098 *
5099 * Convert the xmlSchemaTypeType to a char string.
5100 *
5101 * Returns the char string representation of the facet type if the
5102 * type is a facet and an "Internal Error" string otherwise.
5103 */
5104static const char *
5105xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5106{
5107 switch (type) {
5108 case XML_SCHEMA_FACET_PATTERN:
5109 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005110 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005111 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005112 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005113 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005114 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005115 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005116 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005117 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005118 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005119 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005120 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005121 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005122 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005123 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005124 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005125 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005126 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005127 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005128 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005129 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005130 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005131 return ("fractionDigits");
5132 default:
5133 break;
5134 }
5135 return ("Internal Error");
5136}
5137
5138/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005139 * xmlSchemaValidateFacetsInternal:
5140 * @ctxt: a schema validation context
5141 * @base: the base type
5142 * @facets: the list of facets to check
5143 * @value: the lexical repr of the value to validate
5144 * @val: the precomputed value
5145 * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
5146 *
5147 * Check a value against all facet conditions
5148 *
5149 * Returns 0 if the element is schemas valid, a positive error code
5150 * number otherwise and -1 in case of internal or API error.
5151 */
5152static int
5153xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5154 xmlSchemaTypePtr base,
5155 xmlSchemaFacetPtr facets, const xmlChar * value, int fireErrors)
5156{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005157 int ret = 0;
5158 int tmp = 0;
5159 xmlSchemaTypeType type;
5160 xmlSchemaFacetPtr facet = facets;
5161
5162 while (facet != NULL) {
5163 type = facet->type;
5164 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005165 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005166
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167 while (facet != NULL) {
5168 tmp =
5169 xmlSchemaValidateFacet(base, facet, value,
5170 ctxt->value);
5171 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005172 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005173 }
5174 facet = facet->next;
5175 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005176 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005178
5179 if (tmp != 0) {
5180 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005181 if (fireErrors)
5182 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET, "Failed to validate type with facet %s\n", (const xmlChar *) xmlSchemaFacetTypeToString(type), NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005183 }
5184 if (facet != NULL)
5185 facet = facet->next;
5186 }
5187 return (ret);
5188}
5189
William M. Brack87640d52004-04-17 14:58:15 +00005190/**
5191 * xmlSchemaValidateFacets:
5192 * @ctxt: a schema validation context
5193 * @base: the base type
5194 * @facets: the list of facets to check
5195 * @value: the lexical repr of the value to validate
5196 * @val: the precomputed value
5197 *
5198 * Check a value against all facet conditions
5199 *
5200 * Returns 0 if the element is schemas valid, a positive error code
5201 * number otherwise and -1 in case of internal or API error.
5202 */
5203static int
5204xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5205 xmlSchemaTypePtr base,
5206 xmlSchemaFacetPtr facets, const xmlChar * value)
5207{
5208 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5209}
5210
Daniel Veillard4255d502002-04-16 15:50:10 +00005211/************************************************************************
5212 * *
5213 * Simple type validation *
5214 * *
5215 ************************************************************************/
5216
5217/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005218 * xmlSchemaValidateSimpleValueUnion:
5219 * @ctxt: a schema validation context
5220 * @type: the type declaration
5221 * @value: the value to validate
5222 *
5223 * Validates a value against a union.
5224 *
5225 * Returns 0 if the value is valid, a positive error code
5226 * number otherwise and -1 in case of internal or API error.
5227 */
5228static int
5229xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5230 xmlSchemaTypePtr type, const xmlChar * value)
5231{
5232 int ret = 0;
5233 const xmlChar *cur, *end, *prefix, *ncName;
5234 xmlChar *tmp;
5235 xmlSchemaTypePtr subtype;
5236 xmlNsPtr ns;
5237 int len;
5238
5239
5240 /* Process referenced memberTypes. */
5241 cur = type->ref;
5242 do {
5243 while (IS_BLANK_CH(*cur))
5244 cur++;
5245 end = cur;
5246 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5247 end++;
5248 if (end == cur)
5249 break;
5250 tmp = xmlStrndup(cur, end - cur);
5251 ncName = xmlSplitQName3(tmp, &len);
5252 if (ncName != NULL) {
5253 prefix = xmlStrndup(tmp, len);
5254 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5255 } else {
5256 prefix = NULL;
5257 ncName = tmp;
5258 }
5259 /* We won't do additional checks here, since they have been performed during parsing. */
5260 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5261 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5262 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5263 if (tmp != NULL)
5264 xmlFree(tmp);
5265 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00005266 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005267 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5268 if ((ret == 0) || (ret == -1)) {
5269 return (ret);
5270 }
5271 cur = end;
5272 } while (*cur != 0);
5273
5274 if (type->subtypes != NULL) {
5275 subtype = type->subtypes;
5276 do {
5277 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5278 if ((ret == 0) || (ret == -1)) {
5279 return (ret);
5280 }
5281 subtype = subtype->next;
5282 } while (subtype != NULL);
5283 }
5284 return (ret);
5285}
5286
5287/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005288 * xmlSchemaValidateSimpleValue:
5289 * @ctxt: a schema validation context
5290 * @type: the type declaration
5291 * @value: the value to validate
5292 *
5293 * Validate a value against a simple type
5294 *
5295 * Returns 0 if the value is valid, a positive error code
5296 * number otherwise and -1 in case of internal or API error.
5297 */
5298static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005299xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005300 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005301{
Daniel Veillard377e1a92004-04-16 16:30:05 +00005302 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5303}
5304
5305/**
5306 * xmlSchemaValidateSimpleValue:
5307 * @ctxt: a schema validation context
5308 * @type: the type declaration
5309 * @value: the value to validate
5310 * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
5311 *
5312 * Validate a value against a simple type
5313 *
5314 * Returns 0 if the value is valid, a positive error code
5315 * number otherwise and -1 in case of internal or API error.
5316 */
5317static int
5318xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
5319 xmlSchemaTypePtr type, const xmlChar * value, int fireErrors)
5320{
Daniel Veillard4255d502002-04-16 15:50:10 +00005321 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005322
Daniel Veillard4255d502002-04-16 15:50:10 +00005323 /*
5324 * First normalize the value accordingly to Schema Datatype
5325 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5326 */
5327 /*
5328 * Then check the normalized value against the lexical space of the
5329 * type.
5330 */
5331 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005332 if (ctxt->value != NULL) {
5333 xmlSchemaFreeValue(ctxt->value);
5334 ctxt->value = NULL;
5335 }
5336 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5337 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005338 if ((fireErrors) && (ret != 0)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005339 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate basic type %s\n", type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005340 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005341 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005342 xmlSchemaTypePtr base;
5343 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005344
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005345 base = type->baseType;
5346 if (base != NULL) {
Daniel Veillard377e1a92004-04-16 16:30:05 +00005347 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005348 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005349 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005351
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005352 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005353 * Do not validate facets or attributes when working on
5354 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005355 */
5356 if (ctxt->schema != NULL) {
5357 if (ret == 0) {
5358 facet = type->facets;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005359 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 }
5361 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005362 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005363 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005364
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005365 base = type->subtypes;
5366 if (base != NULL) {
Daniel Veillard377e1a92004-04-16 16:30:05 +00005367 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005368 } else {
5369 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005370 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005371 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005372 const xmlChar *cur, *end;
5373 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005374 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005375
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376 base = type->subtypes;
5377 if (base == NULL) {
5378 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5379 "Internal: List type %s has no base type\n",
5380 type->name, NULL);
5381 return (-1);
5382 }
5383 cur = value;
5384 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005385 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005386 cur++;
5387 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005388 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389 end++;
5390 if (end == cur)
5391 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005392 tmp = xmlStrndup(cur, end - cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005393 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base, tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005394 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005395 if (ret2 != 0)
5396 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005397 cur = end;
5398 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005399 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
5400 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5401 if ((fireErrors) && (ret != 0)) {
5402 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate type %s\n", type->name, NULL);
5403 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005404 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005405 TODO
5406 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005408}
5409
5410/************************************************************************
5411 * *
5412 * DOM Validation code *
5413 * *
5414 ************************************************************************/
5415
5416static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005418static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005419 xmlNodePtr elem,
5420 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005421static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005422 xmlNodePtr elem,
5423 xmlSchemaElementPtr elemDecl,
5424 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005425
5426/**
5427 * xmlSchemaRegisterAttributes:
5428 * @ctxt: a schema validation context
5429 * @attrs: a list of attributes
5430 *
5431 * Register the list of attributes as the set to be validated on that element
5432 *
5433 * Returns -1 in case of error, 0 otherwise
5434 */
5435static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005436xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5437{
Daniel Veillard4255d502002-04-16 15:50:10 +00005438 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005439 if ((attrs->ns != NULL) &&
5440 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5441 attrs = attrs->next;
5442 continue;
5443 }
5444 if (ctxt->attrNr >= ctxt->attrMax) {
5445 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005446
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005447 ctxt->attrMax *= 2;
5448 tmp = (xmlSchemaAttrStatePtr)
5449 xmlRealloc(ctxt->attr, ctxt->attrMax *
5450 sizeof(xmlSchemaAttrState));
5451 if (tmp == NULL) {
5452 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5453 ctxt->attrMax /= 2;
5454 return (-1);
5455 }
5456 ctxt->attr = tmp;
5457 }
5458 ctxt->attr[ctxt->attrNr].attr = attrs;
5459 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5460 ctxt->attrNr++;
5461 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005462 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005463 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005464}
5465
5466/**
5467 * xmlSchemaCheckAttributes:
5468 * @ctxt: a schema validation context
5469 * @node: the node carrying it.
5470 *
5471 * Check that the registered set of attributes on the current node
5472 * has been properly validated.
5473 *
5474 * Returns 0 if validity constraints are met, 1 otherwise.
5475 */
5476static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005477xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5478{
Daniel Veillard4255d502002-04-16 15:50:10 +00005479 int ret = 0;
5480 int i;
5481
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005482 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5483 if (ctxt->attr[i].attr == NULL)
5484 break;
5485 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5486 ret = 1;
5487 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5488 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005489 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005490 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005491}
5492
5493/**
5494 * xmlSchemaValidateSimpleContent:
5495 * @ctxt: a schema validation context
5496 * @elem: an element
5497 * @type: the type declaration
5498 *
5499 * Validate the content of an element expected to be a simple type
5500 *
5501 * Returns 0 if the element is schemas valid, a positive error code
5502 * number otherwise and -1 in case of internal or API error.
5503 */
5504static int
5505xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005506 xmlNodePtr node ATTRIBUTE_UNUSED)
5507{
Daniel Veillard4255d502002-04-16 15:50:10 +00005508 xmlNodePtr child;
5509 xmlSchemaTypePtr type, base;
5510 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005511 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005512
5513 child = ctxt->node;
5514 type = ctxt->type;
5515
5516 /*
5517 * Validation Rule: Element Locally Valid (Type): 3.1.3
5518 */
5519 value = xmlNodeGetContent(child);
5520 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5521 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005522 case XML_SCHEMA_TYPE_RESTRICTION:{
5523 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005524
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005525 base = type->baseType;
5526 if (base != NULL) {
5527 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5528 } else {
5529 TODO}
5530 if (ret == 0) {
5531 facet = type->facets;
5532 ret =
5533 xmlSchemaValidateFacets(ctxt, base, facet, value);
5534 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005535 if ((ret == 0) && (type->attributes != NULL)) {
5536 ret = xmlSchemaValidateAttributes(ctxt, node,
5537 type->attributes);
5538 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005539 break;
5540 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005541 case XML_SCHEMA_TYPE_EXTENSION:{
5542 TODO
5543 break;
5544 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005545 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005546 TODO
5547 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005548 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005549 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005550
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005551 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005552}
5553
5554/**
5555 * xmlSchemaValidateCheckNodeList
5556 * @nodelist: the list of nodes
5557 *
5558 * Check the node list is only made of text nodes and entities pointing
5559 * to text nodes
5560 *
5561 * Returns 1 if true, 0 if false and -1 in case of error
5562 */
5563static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005564xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5565{
Daniel Veillard4255d502002-04-16 15:50:10 +00005566 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005567 if (nodelist->type == XML_ENTITY_REF_NODE) {
5568 TODO /* implement recursion in the entity content */
5569 }
5570 if ((nodelist->type != XML_TEXT_NODE) &&
5571 (nodelist->type != XML_COMMENT_NODE) &&
5572 (nodelist->type != XML_PI_NODE) &&
5573 (nodelist->type != XML_PI_NODE)) {
5574 return (0);
5575 }
5576 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005577 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005578 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005579}
5580
5581/**
5582 * xmlSchemaSkipIgnored:
5583 * @ctxt: a schema validation context
5584 * @type: the current type context
5585 * @node: the top node.
5586 *
5587 * Skip ignorable nodes in that context
5588 *
5589 * Returns the new sibling
5590 * number otherwise and -1 in case of internal or API error.
5591 */
5592static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005593xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005594 xmlSchemaTypePtr type, xmlNodePtr node)
5595{
Daniel Veillard4255d502002-04-16 15:50:10 +00005596 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005597
Daniel Veillard4255d502002-04-16 15:50:10 +00005598 /*
5599 * TODO complete and handle entities
5600 */
5601 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005602 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005603 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005604 ((node->type == XML_COMMENT_NODE) ||
5605 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5606 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5607 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5608 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005610 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005611}
5612
5613/**
5614 * xmlSchemaValidateCallback:
5615 * @ctxt: a schema validation context
5616 * @name: the name of the element detected (might be NULL)
5617 * @type: the type
5618 *
5619 * A transition has been made in the automata associated to an element
5620 * content model
5621 */
5622static void
5623xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005624 const xmlChar * name ATTRIBUTE_UNUSED,
5625 xmlSchemaTypePtr type, xmlNodePtr node)
5626{
Daniel Veillard4255d502002-04-16 15:50:10 +00005627 xmlSchemaTypePtr oldtype = ctxt->type;
5628 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005629
Daniel Veillard4255d502002-04-16 15:50:10 +00005630#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005631 xmlGenericError(xmlGenericErrorContext,
5632 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005634#endif
5635 ctxt->type = type;
5636 ctxt->node = node;
5637 xmlSchemaValidateContent(ctxt, node);
5638 ctxt->type = oldtype;
5639 ctxt->node = oldnode;
5640}
5641
5642
5643#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005644
Daniel Veillard4255d502002-04-16 15:50:10 +00005645/**
5646 * xmlSchemaValidateSimpleRestrictionType:
5647 * @ctxt: a schema validation context
5648 * @node: the top node.
5649 *
5650 * Validate the content of a restriction type.
5651 *
5652 * Returns 0 if the element is schemas valid, a positive error code
5653 * number otherwise and -1 in case of internal or API error.
5654 */
5655static int
5656xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5657 xmlNodePtr node)
5658{
5659 xmlNodePtr child;
5660 xmlSchemaTypePtr type;
5661 int ret;
5662
5663 child = ctxt->node;
5664 type = ctxt->type;
5665
5666 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005667 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005668 return (-1);
5669 }
5670 /*
5671 * Only text and text based entities references shall be found there
5672 */
5673 ret = xmlSchemaValidateCheckNodeList(child);
5674 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005675 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005676 return (-1);
5677 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005678 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005679 return (-1);
5680 }
5681 ctxt->type = type->subtypes;
5682 xmlSchemaValidateContent(ctxt, node);
5683 ctxt->type = type;
5684 return (ret);
5685}
5686#endif
5687
5688/**
5689 * xmlSchemaValidateSimpleType:
5690 * @ctxt: a schema validation context
5691 * @node: the top node.
5692 *
5693 * Validate the content of an simple type.
5694 *
5695 * Returns 0 if the element is schemas valid, a positive error code
5696 * number otherwise and -1 in case of internal or API error.
5697 */
5698static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005699xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5700{
Daniel Veillard4255d502002-04-16 15:50:10 +00005701 xmlNodePtr child;
5702 xmlSchemaTypePtr type;
5703 xmlAttrPtr attr;
5704 int ret;
5705
5706 child = ctxt->node;
5707 type = ctxt->type;
5708
5709 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005710 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5711 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005712 }
5713 /*
5714 * Only text and text based entities references shall be found there
5715 */
5716 ret = xmlSchemaValidateCheckNodeList(child);
5717 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005718 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5719 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005720 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005721 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5722 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005723 }
5724 /*
5725 * Validation Rule: Element Locally Valid (Type): 3.1.1
5726 */
5727 attr = node->properties;
5728 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005729 if ((attr->ns == NULL) ||
5730 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5731 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5732 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5733 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5734 (!xmlStrEqual
5735 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5736 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5737 return (ctxt->err);
5738 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005739 }
5740
5741 ctxt->type = type->subtypes;
5742 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5743 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005744 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005745}
5746
5747/**
5748 * xmlSchemaValidateElementType:
5749 * @ctxt: a schema validation context
5750 * @node: the top node.
5751 *
5752 * Validate the content of an element type.
5753 * Validation Rule: Element Locally Valid (Complex Type)
5754 *
5755 * Returns 0 if the element is schemas valid, a positive error code
5756 * number otherwise and -1 in case of internal or API error.
5757 */
5758static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005759xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5760{
Daniel Veillard4255d502002-04-16 15:50:10 +00005761 xmlNodePtr child;
5762 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005763 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005764 xmlSchemaElementPtr decl;
5765 int ret, attrBase;
5766
5767 oldregexp = ctxt->regexp;
5768
5769 child = ctxt->node;
5770 type = ctxt->type;
5771
5772 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005773 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5774 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005775 }
5776 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005777 if (type->minOccurs > 0) {
5778 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5779 }
5780 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005781 }
5782
5783 /*
5784 * Verify the element matches
5785 */
5786 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005787 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5788 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005789 }
5790 /*
5791 * Verify the attributes
5792 */
5793 attrBase = ctxt->attrBase;
5794 ctxt->attrBase = ctxt->attrNr;
5795 xmlSchemaRegisterAttributes(ctxt, child->properties);
5796 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5797 /*
5798 * Verify the element content recursively
5799 */
5800 decl = (xmlSchemaElementPtr) type;
5801 oldregexp = ctxt->regexp;
5802 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5804 (xmlRegExecCallbacks)
5805 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005806#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005807 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005808#endif
5809 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5811 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005812
5813 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005815#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 xmlGenericError(xmlGenericErrorContext,
5817 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005818#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005819 if (ret == 0) {
5820 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5821 } else if (ret < 0) {
5822 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005823#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else {
5825 xmlGenericError(xmlGenericErrorContext,
5826 "Element %s content check succeeded\n",
5827 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005828
5829#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005830 }
5831 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005832 }
5833 /*
5834 * Verify that all attributes were Schemas-validated
5835 */
5836 xmlSchemaCheckAttributes(ctxt, node);
5837 ctxt->attrNr = ctxt->attrBase;
5838 ctxt->attrBase = attrBase;
5839
5840 ctxt->regexp = oldregexp;
5841
5842 ctxt->node = child;
5843 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005844 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005845}
5846
5847/**
5848 * xmlSchemaValidateBasicType:
5849 * @ctxt: a schema validation context
5850 * @node: the top node.
5851 *
5852 * Validate the content of an element expected to be a basic type type
5853 *
5854 * Returns 0 if the element is schemas valid, a positive error code
5855 * number otherwise and -1 in case of internal or API error.
5856 */
5857static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005858xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5859{
Daniel Veillard4255d502002-04-16 15:50:10 +00005860 int ret;
5861 xmlNodePtr child, cur;
5862 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005863 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005864
5865 child = ctxt->node;
5866 type = ctxt->type;
5867
5868 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005869 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5870 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005871 }
5872 /*
5873 * First check the content model of the node.
5874 */
5875 cur = child;
5876 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005877 switch (cur->type) {
5878 case XML_TEXT_NODE:
5879 case XML_CDATA_SECTION_NODE:
5880 case XML_PI_NODE:
5881 case XML_COMMENT_NODE:
5882 case XML_XINCLUDE_START:
5883 case XML_XINCLUDE_END:
5884 break;
5885 case XML_ENTITY_REF_NODE:
5886 case XML_ENTITY_NODE:
5887 TODO break;
5888 case XML_ELEMENT_NODE:
5889 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5890 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005891 case XML_ATTRIBUTE_NODE:
5892 case XML_DOCUMENT_NODE:
5893 case XML_DOCUMENT_TYPE_NODE:
5894 case XML_DOCUMENT_FRAG_NODE:
5895 case XML_NOTATION_NODE:
5896 case XML_HTML_DOCUMENT_NODE:
5897 case XML_DTD_NODE:
5898 case XML_ELEMENT_DECL:
5899 case XML_ATTRIBUTE_DECL:
5900 case XML_ENTITY_DECL:
5901 case XML_NAMESPACE_DECL:
5902#ifdef LIBXML_DOCB_ENABLED
5903 case XML_DOCB_DOCUMENT_NODE:
5904#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005905 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5906 return (ctxt->err);
5907 }
5908 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005909 }
5910 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005911 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005912 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005913 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005914
5915 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005916 xmlSchemaFreeValue(ctxt->value);
5917 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005918 }
5919 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5920 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005921 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005922 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005923 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE, "Element %s: failed to validate basic type %s\n", node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005924 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005925 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005926}
5927
5928/**
5929 * xmlSchemaValidateComplexType:
5930 * @ctxt: a schema validation context
5931 * @node: the top node.
5932 *
5933 * Validate the content of an element expected to be a complex type type
5934 * xmlschema-1.html#cvc-complex-type
5935 * Validation Rule: Element Locally Valid (Complex Type)
5936 *
5937 * Returns 0 if the element is schemas valid, a positive error code
5938 * number otherwise and -1 in case of internal or API error.
5939 */
5940static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005941xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5942{
Daniel Veillard4255d502002-04-16 15:50:10 +00005943 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005944 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005945 int ret;
5946
5947 child = ctxt->node;
5948 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005949 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005950
Daniel Veillard4255d502002-04-16 15:50:10 +00005951 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005952 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005953 if (type->baseType != NULL) {
5954 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005955 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5956 }
5957 if (type->attributes != NULL) {
5958 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5959 }
5960 subtype = type->subtypes;
5961 while (subtype != NULL) {
5962 ctxt->type = subtype;
5963 xmlSchemaValidateComplexType(ctxt, node);
5964 subtype = subtype->next;
5965 }
5966 break;
5967 case XML_SCHEMA_CONTENT_ELEMENTS:
5968 case XML_SCHEMA_CONTENT_MIXED:
5969 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5970 /*
5971 * Skip ignorable nodes in that context
5972 */
5973 child = xmlSchemaSkipIgnored(ctxt, type, child);
5974 while (child != NULL) {
5975 if (child->type == XML_ELEMENT_NODE) {
5976 ret = xmlRegExecPushString(ctxt->regexp,
5977 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005978#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005979 if (ret < 0)
5980 xmlGenericError(xmlGenericErrorContext,
5981 " --> %s Error\n", child->name);
5982 else
5983 xmlGenericError(xmlGenericErrorContext,
5984 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005985#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005986 }
5987 child = child->next;
5988 /*
5989 * Skip ignorable nodes in that context
5990 */
5991 child = xmlSchemaSkipIgnored(ctxt, type, child);
5992 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005993 if (type->attributes != NULL) {
5994 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5995 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005996 break;
5997 case XML_SCHEMA_CONTENT_BASIC:{
5998 if (type->subtypes != NULL) {
5999 ctxt->type = type->subtypes;
6000 xmlSchemaValidateComplexType(ctxt, node);
6001 }
6002 if (type->baseType != NULL) {
6003 ctxt->type = type->baseType;
6004 xmlSchemaValidateBasicType(ctxt, node);
6005 }
6006 if (type->attributes != NULL) {
6007 xmlSchemaValidateAttributes(ctxt, node,
6008 type->attributes);
6009 }
6010 ctxt->type = type;
6011 break;
6012 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006013 case XML_SCHEMA_CONTENT_SIMPLE:{
6014 if (type->subtypes != NULL) {
6015 ctxt->type = type->subtypes;
6016 xmlSchemaValidateComplexType(ctxt, node);
6017 }
6018 if (type->baseType != NULL) {
6019 ctxt->type = type->baseType;
6020 xmlSchemaValidateComplexType(ctxt, node);
6021 }
6022 if (type->attributes != NULL) {
6023 xmlSchemaValidateAttributes(ctxt, node,
6024 type->attributes);
6025 }
6026 ctxt->type = type;
6027 break;
6028 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006029 default:
6030 TODO xmlGenericError(xmlGenericErrorContext,
6031 "unimplemented content type %d\n",
6032 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006035}
6036
6037/**
6038 * xmlSchemaValidateContent:
6039 * @ctxt: a schema validation context
6040 * @elem: an element
6041 * @type: the type declaration
6042 *
6043 * Validate the content of an element against the type.
6044 *
6045 * Returns 0 if the element is schemas valid, a positive error code
6046 * number otherwise and -1 in case of internal or API error.
6047 */
6048static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006049xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6050{
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 xmlNodePtr child;
6052 xmlSchemaTypePtr type;
6053
6054 child = ctxt->node;
6055 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006056 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006057
Daniel Veillarde19fc232002-04-22 16:01:24 +00006058 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006059 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00006060
Daniel Veillard4255d502002-04-16 15:50:10 +00006061 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006062 case XML_SCHEMA_TYPE_ANY:
6063 /* Any type will do it, fine */
6064 TODO /* handle recursivity */
6065 break;
6066 case XML_SCHEMA_TYPE_COMPLEX:
6067 xmlSchemaValidateComplexType(ctxt, node);
6068 break;
6069 case XML_SCHEMA_TYPE_ELEMENT:{
6070 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6071
6072 /*
6073 * Handle element reference here
6074 */
6075 if (decl->ref != NULL) {
6076 if (decl->refDecl == NULL) {
6077 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
6078 return (-1);
6079 }
6080 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6081 decl = decl->refDecl;
6082 }
6083 xmlSchemaValidateElementType(ctxt, node);
6084 ctxt->type = type;
6085 break;
6086 }
6087 case XML_SCHEMA_TYPE_BASIC:
6088 xmlSchemaValidateBasicType(ctxt, node);
6089 break;
6090 case XML_SCHEMA_TYPE_FACET:
6091 TODO break;
6092 case XML_SCHEMA_TYPE_SIMPLE:
6093 xmlSchemaValidateSimpleType(ctxt, node);
6094 break;
6095 case XML_SCHEMA_TYPE_SEQUENCE:
6096 TODO break;
6097 case XML_SCHEMA_TYPE_CHOICE:
6098 TODO break;
6099 case XML_SCHEMA_TYPE_ALL:
6100 TODO break;
6101 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6102 TODO break;
6103 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6104 TODO break;
6105 case XML_SCHEMA_TYPE_UR:
6106 TODO break;
6107 case XML_SCHEMA_TYPE_RESTRICTION:
6108 /*xmlSchemaValidateRestrictionType(ctxt, node); */
6109 TODO break;
6110 case XML_SCHEMA_TYPE_EXTENSION:
6111 TODO break;
6112 case XML_SCHEMA_TYPE_ATTRIBUTE:
6113 TODO break;
6114 case XML_SCHEMA_TYPE_GROUP:
6115 TODO break;
6116 case XML_SCHEMA_TYPE_NOTATION:
6117 TODO break;
6118 case XML_SCHEMA_TYPE_LIST:
6119 TODO break;
6120 case XML_SCHEMA_TYPE_UNION:
6121 TODO break;
6122 case XML_SCHEMA_FACET_MININCLUSIVE:
6123 TODO break;
6124 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6125 TODO break;
6126 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6127 TODO break;
6128 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6129 TODO break;
6130 case XML_SCHEMA_FACET_TOTALDIGITS:
6131 TODO break;
6132 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6133 TODO break;
6134 case XML_SCHEMA_FACET_PATTERN:
6135 TODO break;
6136 case XML_SCHEMA_FACET_ENUMERATION:
6137 TODO break;
6138 case XML_SCHEMA_FACET_WHITESPACE:
6139 TODO break;
6140 case XML_SCHEMA_FACET_LENGTH:
6141 TODO break;
6142 case XML_SCHEMA_FACET_MAXLENGTH:
6143 TODO break;
6144 case XML_SCHEMA_FACET_MINLENGTH:
6145 TODO break;
6146 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6147 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00006148 }
6149 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6150
6151 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006152 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006153 ctxt->node = ctxt->node->next;
6154 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006155 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006156}
6157
6158/**
6159 * xmlSchemaValidateType:
6160 * @ctxt: a schema validation context
6161 * @elem: an element
6162 * @type: the list of type declarations
6163 *
6164 * Validate the content of an element against the types.
6165 *
6166 * Returns 0 if the element is schemas valid, a positive error code
6167 * number otherwise and -1 in case of internal or API error.
6168 */
6169static int
6170xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006171 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6172{
Daniel Veillard4255d502002-04-16 15:50:10 +00006173 xmlChar *nil;
6174
Daniel Veillard2db8c122003-07-08 12:16:59 +00006175 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006176 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00006177
Daniel Veillard4255d502002-04-16 15:50:10 +00006178 /*
6179 * 3.3.4 : 2
6180 */
6181 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006182 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
6183 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006184 }
6185 /*
6186 * 3.3.4: 3
6187 */
6188 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6189 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006190 /* 3.3.4: 3.2 */
6191 if (xmlStrEqual(nil, BAD_CAST "true")) {
6192 if (elem->children != NULL) {
6193 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
6194 return (ctxt->err);
6195 }
6196 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6197 (elemDecl->value != NULL)) {
6198 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
6199 return (ctxt->err);
6200 }
6201 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006203 /* 3.3.4: 3.1 */
6204 if (nil != NULL) {
6205 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
6206 xmlFree(nil);
6207 return (ctxt->err);
6208 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006209 }
6210
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006211 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006212
6213 ctxt->type = elemDecl->subtypes;
6214 ctxt->node = elem->children;
6215 xmlSchemaValidateContent(ctxt, elem);
6216 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006217
6218 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006219}
6220
6221
6222/**
6223 * xmlSchemaValidateAttributes:
6224 * @ctxt: a schema validation context
6225 * @elem: an element
6226 * @attributes: the list of attribute declarations
6227 *
6228 * Validate the attributes of an element.
6229 *
6230 * Returns 0 if the element is schemas valid, a positive error code
6231 * number otherwise and -1 in case of internal or API error.
6232 */
6233static int
6234xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006235 xmlSchemaAttributePtr attributes)
6236{
William M. Brack87640d52004-04-17 14:58:15 +00006237 int i, ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006238 xmlAttrPtr attr;
6239 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006240 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006241 int found;
Daniel Veillard4255d502002-04-16 15:50:10 +00006242
6243 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006244 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006245 while (attributes != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006246 found = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006247 /*
6248 * Handle attribute groups
6249 */
6250 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6251 group = (xmlSchemaAttributeGroupPtr) attributes;
6252 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6253 attributes = group->next;
6254 continue;
6255 }
6256 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6257 attr = ctxt->attr[i].attr;
6258 if (attr == NULL)
6259 continue;
6260 if (attributes->ref != NULL) {
6261 if (!xmlStrEqual(attr->name, attributes->ref))
6262 continue;
6263 if (attr->ns != NULL) {
6264 if ((attributes->refNs == NULL) ||
6265 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6266 continue;
6267 } else if (attributes->refNs != NULL) {
6268 continue;
6269 }
6270 } else {
6271 if (!xmlStrEqual(attr->name, attributes->name))
6272 continue;
6273 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006274 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006275 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006276 if (attr->ns == NULL) {
6277 /*
6278 * accept an unqualified attribute only if the declaration
6279 * is unqualified or if the schemas allowed it.
6280 */
6281 if ((attributes->targetNamespace != NULL) &&
6282 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6283 continue;
6284 } else {
6285 if (attributes->targetNamespace == NULL)
6286 continue;
6287 if (!xmlStrEqual(attributes->targetNamespace,
6288 attr->ns->href))
6289 continue;
6290 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006291 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006292 found = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006293 ctxt->cur = (xmlNodePtr) attributes;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006294
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006295 if (attributes->subtypes == NULL) {
6296 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6297 continue;
6298 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006299
6300 if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6301 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR, "attribute %s on %s is prohibited\n", attributes->name, elem->name);
6302 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems not very logical but it
6303 surpresses the "attribute is unknown" error report. Please change this if you know better */
6304 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6305 break;
6306 }
6307
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006308 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6309 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6310 value);
6311 if (ret != 0) {
6312 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6313 } else {
6314 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6315 }
6316 if (value != NULL) {
6317 xmlFree(value);
6318 }
6319 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006320 if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6321 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING, "required attribute %s on %s is missing\n", attributes->name, elem->name);
6322 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006323 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006324 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006325 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006326}
6327
6328/**
6329 * xmlSchemaValidateElement:
6330 * @ctxt: a schema validation context
6331 * @elem: an element
6332 *
6333 * Validate an element in a tree
6334 *
6335 * Returns 0 if the element is schemas valid, a positive error code
6336 * number otherwise and -1 in case of internal or API error.
6337 */
6338static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006339xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6340{
Daniel Veillard4255d502002-04-16 15:50:10 +00006341 xmlSchemaElementPtr elemDecl;
6342 int ret, attrBase;
6343
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006344 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006345 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6346 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006347 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006348 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6349 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006350 }
6351 /*
6352 * special case whe elementFormDefault is unqualified for top-level elem.
6353 */
6354 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6355 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6356 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6357 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6358 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6359 elem->name, NULL, NULL);
6360 }
6361
Daniel Veillard4255d502002-04-16 15:50:10 +00006362 /*
6363 * 3.3.4 : 1
6364 */
6365 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006366 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6367 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006368 }
6369 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006370 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6371 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006372 }
6373 /*
6374 * Verify the attributes
6375 */
6376 attrBase = ctxt->attrBase;
6377 ctxt->attrBase = ctxt->attrNr;
6378 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6379 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6380 /*
6381 * Verify the element content recursively
6382 */
6383 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006384 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6385 (xmlRegExecCallbacks)
6386 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006387#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006388 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006389#endif
6390 }
6391 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006392 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006393 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006394#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006395 xmlGenericError(xmlGenericErrorContext,
6396 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006397#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006398 if (ret == 0) {
6399 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6400 } else if (ret < 0) {
6401 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006402#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006403 } else {
6404 xmlGenericError(xmlGenericErrorContext,
6405 "Element %s content check succeeded\n",
6406 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006407
6408#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006409 }
6410 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006411 }
6412 /*
6413 * Verify that all attributes were Schemas-validated
6414 */
6415 xmlSchemaCheckAttributes(ctxt, elem);
6416 ctxt->attrNr = ctxt->attrBase;
6417 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006418
6419 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006420}
6421
6422/**
6423 * xmlSchemaValidateDocument:
6424 * @ctxt: a schema validation context
6425 * @doc: a parsed document tree
6426 *
6427 * Validate a document tree in memory.
6428 *
6429 * Returns 0 if the document is schemas valid, a positive error code
6430 * number otherwise and -1 in case of internal or API error.
6431 */
6432static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006433xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6434{
Daniel Veillard4255d502002-04-16 15:50:10 +00006435 xmlNodePtr root;
6436 xmlSchemaElementPtr elemDecl;
6437
6438 root = xmlDocGetRootElement(doc);
6439 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006440 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6441 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006442 }
6443 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006444 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6445 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006446 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006447 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6448 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006449 /*
6450 * special case whe elementFormDefault is unqualified for top-level elem.
6451 */
6452 if ((elemDecl == NULL) && (root->ns != NULL) &&
6453 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6454 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6455 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6456 root->name, NULL, NULL);
6457 }
6458
Daniel Veillard4255d502002-04-16 15:50:10 +00006459 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006460 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006461 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006462 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006463 }
6464 /*
6465 * Okay, start the recursive validation
6466 */
6467 xmlSchemaValidateElement(ctxt, root);
6468
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006469 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006470}
6471
6472/************************************************************************
6473 * *
6474 * SAX Validation code *
6475 * *
6476 ************************************************************************/
6477
6478/************************************************************************
6479 * *
6480 * Validation interfaces *
6481 * *
6482 ************************************************************************/
6483
6484/**
6485 * xmlSchemaNewValidCtxt:
6486 * @schema: a precompiled XML Schemas
6487 *
6488 * Create an XML Schemas validation context based on the given schema
6489 *
6490 * Returns the validation context or NULL in case of error
6491 */
6492xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006493xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6494{
Daniel Veillard4255d502002-04-16 15:50:10 +00006495 xmlSchemaValidCtxtPtr ret;
6496
6497 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6498 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006499 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006500 return (NULL);
6501 }
6502 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6503 ret->schema = schema;
6504 ret->attrNr = 0;
6505 ret->attrMax = 10;
6506 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006507 sizeof
6508 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006509 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006510 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6511 free(ret);
6512 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006513 }
6514 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6515 return (ret);
6516}
6517
6518/**
6519 * xmlSchemaFreeValidCtxt:
6520 * @ctxt: the schema validation context
6521 *
6522 * Free the resources associated to the schema validation context
6523 */
6524void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006525xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6526{
Daniel Veillard4255d502002-04-16 15:50:10 +00006527 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006528 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006529 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006530 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006531 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006532 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006533 xmlFree(ctxt);
6534}
6535
6536/**
6537 * xmlSchemaSetValidErrors:
6538 * @ctxt: a schema validation context
6539 * @err: the error function
6540 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006541 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006542 *
6543 * Set the error and warning callback informations
6544 */
6545void
6546xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006547 xmlSchemaValidityErrorFunc err,
6548 xmlSchemaValidityWarningFunc warn, void *ctx)
6549{
Daniel Veillard4255d502002-04-16 15:50:10 +00006550 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006551 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006552 ctxt->error = err;
6553 ctxt->warning = warn;
6554 ctxt->userData = ctx;
6555}
6556
6557/**
6558 * xmlSchemaValidateDoc:
6559 * @ctxt: a schema validation context
6560 * @doc: a parsed document tree
6561 *
6562 * Validate a document tree in memory.
6563 *
6564 * Returns 0 if the document is schemas valid, a positive error code
6565 * number otherwise and -1 in case of internal or API error.
6566 */
6567int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006568xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6569{
Daniel Veillard4255d502002-04-16 15:50:10 +00006570 int ret;
6571
6572 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006573 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006574
6575 ctxt->doc = doc;
6576 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006577 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006578}
6579
6580/**
6581 * xmlSchemaValidateStream:
6582 * @ctxt: a schema validation context
6583 * @input: the input to use for reading the data
6584 * @enc: an optional encoding information
6585 * @sax: a SAX handler for the resulting events
6586 * @user_data: the context to provide to the SAX handler.
6587 *
6588 * Validate a document tree in memory.
6589 *
6590 * Returns 0 if the document is schemas valid, a positive error code
6591 * number otherwise and -1 in case of internal or API error.
6592 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006593int
Daniel Veillard4255d502002-04-16 15:50:10 +00006594xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006595 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6596 xmlSAXHandlerPtr sax, void *user_data)
6597{
Daniel Veillard4255d502002-04-16 15:50:10 +00006598 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006599 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006600 ctxt->input = input;
6601 ctxt->enc = enc;
6602 ctxt->sax = sax;
6603 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006604 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006605}
6606
6607#endif /* LIBXML_SCHEMAS_ENABLED */