blob: 25f94001a4e39e7c10a7fc5167d4043fe4997dbe [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 }
Daniel Veillard2582a332004-04-18 19:49:46 +00004551 if (typeDecl->recurse) {
4552 xmlSchemaPErr(ctxt, typeDecl->node,
4553 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4554 "Schemas: extension type %s is recursive\n",
4555 name, NULL);
4556 return;
4557 }
4558 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004559 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00004560 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004561 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4562 /* 2.1 */
4563 typeDecl->contentType = base->contentType;
4564 } else if (base->contentType ==
4565 XML_SCHEMA_CONTENT_EMPTY) {
4566 /* 2.2 imbitable ! */
4567 typeDecl->contentType =
4568 XML_SCHEMA_CONTENT_ELEMENTS;
4569 } else {
4570 /* 2.3 imbitable pareil ! */
4571 typeDecl->contentType =
4572 XML_SCHEMA_CONTENT_ELEMENTS;
4573 }
4574 break;
4575 }
4576 case XML_SCHEMA_TYPE_COMPLEX:{
4577 if (typeDecl->subtypes == NULL) {
4578 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004579
4580 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4581 typeDecl->contentType =
4582 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 } else {
4584 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4585 typeDecl->contentType =
4586 XML_SCHEMA_CONTENT_MIXED;
4587 else {
4588 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4589 NULL);
4590 if (typeDecl->subtypes != NULL)
4591 typeDecl->contentType =
4592 typeDecl->subtypes->contentType;
4593 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004594 if (typeDecl->attributes == NULL)
4595 typeDecl->attributes =
4596 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004597 }
4598 break;
4599 }
4600 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4601 if (typeDecl->subtypes == NULL) {
4602 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004603 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4604 typeDecl->contentType =
4605 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004606 } else {
4607 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4608 typeDecl->contentType =
4609 XML_SCHEMA_CONTENT_MIXED;
4610 else {
4611 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4612 NULL);
4613 if (typeDecl->subtypes != NULL)
4614 typeDecl->contentType =
4615 typeDecl->subtypes->contentType;
4616 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004617 if (typeDecl->attributes == NULL)
4618 typeDecl->attributes =
4619 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004620 }
4621 break;
4622 }
4623 case XML_SCHEMA_TYPE_SEQUENCE:
4624 case XML_SCHEMA_TYPE_GROUP:
4625 case XML_SCHEMA_TYPE_ALL:
4626 case XML_SCHEMA_TYPE_CHOICE:
4627 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4628 break;
4629 case XML_SCHEMA_TYPE_BASIC:
4630 case XML_SCHEMA_TYPE_ANY:
4631 case XML_SCHEMA_TYPE_FACET:
4632 case XML_SCHEMA_TYPE_SIMPLE:
4633 case XML_SCHEMA_TYPE_UR:
4634 case XML_SCHEMA_TYPE_ELEMENT:
4635 case XML_SCHEMA_TYPE_ATTRIBUTE:
4636 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4637 case XML_SCHEMA_TYPE_NOTATION:
4638 case XML_SCHEMA_TYPE_LIST:
4639 case XML_SCHEMA_TYPE_UNION:
Daniel Veillard377e1a92004-04-16 16:30:05 +00004640 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004641 case XML_SCHEMA_FACET_MININCLUSIVE:
4642 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4643 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4644 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4645 case XML_SCHEMA_FACET_TOTALDIGITS:
4646 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4647 case XML_SCHEMA_FACET_PATTERN:
4648 case XML_SCHEMA_FACET_ENUMERATION:
4649 case XML_SCHEMA_FACET_WHITESPACE:
4650 case XML_SCHEMA_FACET_LENGTH:
4651 case XML_SCHEMA_FACET_MAXLENGTH:
4652 case XML_SCHEMA_FACET_MINLENGTH:
4653 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004654 if (typeDecl->subtypes != NULL)
4655 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004656 break;
4657 }
4658 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004659#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004660 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004661 xmlGenericError(xmlGenericErrorContext,
4662 "Type of %s : %s:%d :", name,
4663 typeDecl->node->doc->URL,
4664 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004665 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004666 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004667 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004668 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004669 case XML_SCHEMA_CONTENT_SIMPLE:
4670 xmlGenericError(xmlGenericErrorContext, "simple\n");
4671 break;
4672 case XML_SCHEMA_CONTENT_ELEMENTS:
4673 xmlGenericError(xmlGenericErrorContext, "elements\n");
4674 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004675 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004676 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4677 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004678 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004679 xmlGenericError(xmlGenericErrorContext, "empty\n");
4680 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004681 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004682 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4683 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004684 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004685 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4686 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004687 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004688 xmlGenericError(xmlGenericErrorContext, "basic\n");
4689 break;
4690 default:
4691 xmlGenericError(xmlGenericErrorContext,
4692 "not registered !!!\n");
4693 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004694 }
4695#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004696}
4697
4698/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004699 * xmlSchemaCheckFacet:
4700 * @facet: the facet
4701 * @typeDecl: the schema type definition
4702 * @ctxt: the schema parser context or NULL
4703 * @name: name of the type
4704 *
4705 * Checks the default values types, especially for facets
4706 *
4707 * Returns 0 if okay or -1 in cae of error
4708 */
4709int
4710xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004711 xmlSchemaTypePtr typeDecl,
4712 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004713{
4714 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4715 int ret = 0;
4716
4717 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004718 nonNegativeIntegerType =
4719 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4720 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004721 }
4722 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004723 case XML_SCHEMA_FACET_MININCLUSIVE:
4724 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4725 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4726 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4727 /*
4728 * Okay we need to validate the value
4729 * at that point.
4730 */
4731 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004732
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004733 vctxt = xmlSchemaNewValidCtxt(NULL);
4734 if (vctxt == NULL)
4735 break;
4736 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4737 facet->value);
4738 facet->val = vctxt->value;
4739 vctxt->value = NULL;
4740 if (facet->val == NULL) {
4741 /* error code */
4742 if (ctxt != NULL) {
4743 xmlSchemaPErr(ctxt, facet->node,
4744 XML_SCHEMAP_INVALID_FACET,
4745 "Schemas: type %s facet value %s invalid\n",
4746 name, facet->value);
4747 }
4748 ret = -1;
4749 }
4750 xmlSchemaFreeValidCtxt(vctxt);
4751 break;
4752 }
4753 case XML_SCHEMA_FACET_ENUMERATION:{
4754 /*
4755 * Okay we need to validate the value
4756 * at that point.
4757 */
4758 xmlSchemaValidCtxtPtr vctxt;
4759 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004760
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004761 vctxt = xmlSchemaNewValidCtxt(NULL);
4762 if (vctxt == NULL)
4763 break;
4764 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4765 facet->value);
4766 if (tmp != 0) {
4767 if (ctxt != NULL) {
4768 xmlSchemaPErr(ctxt, facet->node,
4769 XML_SCHEMAP_INVALID_ENUM,
4770 "Schemas: type %s enumeration value %s invalid\n",
4771 name, facet->value);
4772 }
4773 ret = -1;
4774 }
4775 xmlSchemaFreeValidCtxt(vctxt);
4776 break;
4777 }
4778 case XML_SCHEMA_FACET_PATTERN:
4779 facet->regexp = xmlRegexpCompile(facet->value);
4780 if (facet->regexp == NULL) {
4781 xmlSchemaPErr(ctxt, typeDecl->node,
4782 XML_SCHEMAP_REGEXP_INVALID,
4783 "Schemas: type %s facet regexp %s invalid\n",
4784 name, facet->value);
4785 ret = -1;
4786 }
4787 break;
4788 case XML_SCHEMA_FACET_TOTALDIGITS:
4789 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4790 case XML_SCHEMA_FACET_LENGTH:
4791 case XML_SCHEMA_FACET_MAXLENGTH:
4792 case XML_SCHEMA_FACET_MINLENGTH:{
4793 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004794
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004795 tmp =
4796 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4797 facet->value,
4798 &facet->val);
4799 if (tmp != 0) {
4800 /* error code */
4801 if (ctxt != NULL) {
4802 xmlSchemaPErr(ctxt, facet->node,
4803 XML_SCHEMAP_INVALID_FACET_VALUE,
4804 "Schemas: type %s facet value %s invalid\n",
4805 name, facet->value);
4806 }
4807 ret = -1;
4808 }
4809 break;
4810 }
4811 case XML_SCHEMA_FACET_WHITESPACE:{
4812 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4813 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4814 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4815 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4816 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4817 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4818 } else {
4819 if (ctxt != NULL) {
4820 xmlSchemaPErr(ctxt, facet->node,
4821 XML_SCHEMAP_INVALID_WHITE_SPACE,
4822 "Schemas: type %s whiteSpace value %s invalid\n",
4823 name, facet->value);
4824 }
4825 ret = -1;
4826 }
4827 }
4828 default:
4829 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004830 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004832}
4833
4834/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004835 * xmlSchemaCheckDefaults:
4836 * @typeDecl: the schema type definition
4837 * @ctxt: the schema parser context
4838 *
4839 * Checks the default values types, especially for facets
4840 */
4841static void
4842xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004843 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004844{
Daniel Veillard4255d502002-04-16 15:50:10 +00004845 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004846 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004847 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004848 if (typeDecl->facets != NULL) {
4849 xmlSchemaFacetPtr facet = typeDecl->facets;
4850
4851 while (facet != NULL) {
4852 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4853 facet = facet->next;
4854 }
4855 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004856 }
4857}
4858
4859/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004860 * xmlSchemaAttrGrpFixup:
4861 * @attrgrpDecl: the schema attribute definition
4862 * @ctxt: the schema parser context
4863 * @name: the attribute name
4864 *
4865 * Fixes finish doing the computations on the attributes definitions
4866 */
4867static void
4868xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004869 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004870{
4871 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004872 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004873 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004874 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004875 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004876 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004877
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004878 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4879 attrgrpDecl->refNs);
4880 if (ref == NULL) {
4881 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4882 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4883 "Schemas: attribute group %s reference %s not found\n",
4884 name, attrgrpDecl->ref);
4885 return;
4886 }
4887 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4888 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004889 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004890 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4891 "Schemas: attribute %s has no attributes nor reference\n",
4892 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004893 }
4894}
4895
4896/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004897 * xmlSchemaAttrFixup:
4898 * @attrDecl: the schema attribute definition
4899 * @ctxt: the schema parser context
4900 * @name: the attribute name
4901 *
4902 * Fixes finish doing the computations on the attributes definitions
4903 */
4904static void
4905xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004906 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004907{
4908 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004909 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004910 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004911 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004912 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004913 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004914
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4916 attrDecl->typeNs);
4917 if (type == NULL) {
4918 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4919 "Schemas: attribute %s type %s not found\n",
4920 name, attrDecl->typeName);
4921 }
4922 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004923 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004924 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004925
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004926 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4927 attrDecl->refNs);
4928 if (ref == NULL) {
4929 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4930 "Schemas: attribute %s reference %s not found\n",
4931 name, attrDecl->ref);
4932 return;
4933 }
4934 xmlSchemaAttrFixup(ref, ctxt, NULL);
4935 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004936 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004937 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4938 "Schemas: attribute %s has no type nor reference\n",
4939 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004940 }
4941}
4942
4943/**
4944 * xmlSchemaParse:
4945 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004946 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004947 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004948 * XML Shema struture which can be used to validate instances.
4949 * *WARNING* this interface is highly subject to change
4950 *
4951 * Returns the internal XML Schema structure built from the resource or
4952 * NULL in case of error
4953 */
4954xmlSchemaPtr
4955xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4956{
4957 xmlSchemaPtr ret = NULL;
4958 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004959 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004960 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004961 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004962
4963 xmlSchemaInitTypes();
4964
Daniel Veillard6045c902002-10-09 21:13:59 +00004965 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004966 return (NULL);
4967
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004968 nberrors = ctxt->nberrors;
4969 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004970 ctxt->counter = 0;
4971 ctxt->container = NULL;
4972
4973 /*
4974 * First step is to parse the input document into an DOM/Infoset
4975 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004976 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004977 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4978 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004979 if (doc == NULL) {
4980 xmlSchemaPErr(ctxt, NULL,
4981 XML_SCHEMAP_FAILED_LOAD,
4982 "xmlSchemaParse: could not load %s\n",
4983 ctxt->URL, NULL);
4984 return (NULL);
4985 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004986 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004987 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4988 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004989 if (doc == NULL) {
4990 xmlSchemaPErr(ctxt, NULL,
4991 XML_SCHEMAP_FAILED_PARSE,
4992 "xmlSchemaParse: could not parse\n",
4993 NULL, NULL);
4994 return (NULL);
4995 }
4996 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00004997 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00004998 } else if (ctxt->doc != NULL) {
4999 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005000 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00005001 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005002 xmlSchemaPErr(ctxt, NULL,
5003 XML_SCHEMAP_NOTHING_TO_PARSE,
5004 "xmlSchemaParse: could not parse\n",
5005 NULL, NULL);
5006 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005007 }
5008
5009 /*
5010 * Then extract the root and Schema parse it
5011 */
5012 root = xmlDocGetRootElement(doc);
5013 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005014 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5015 XML_SCHEMAP_NOROOT,
5016 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00005017 if (!preserve) {
5018 xmlFreeDoc(doc);
5019 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005020 return (NULL);
5021 }
5022
5023 /*
5024 * Remove all the blank text nodes
5025 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005026 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00005027
5028 /*
5029 * Then do the parsing for good
5030 */
5031 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00005032 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00005033 if (!preserve) {
5034 xmlFreeDoc(doc);
5035 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005036 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00005037 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005038 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005039 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00005040
5041 /*
5042 * Then fix all the references.
5043 */
5044 ctxt->schema = ret;
5045 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005046 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005047
5048 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005049 * Then fixup all attributes declarations
5050 */
5051 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5052
5053 /*
5054 * Then fixup all attributes group declarations
5055 */
5056 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5057 ctxt);
5058
5059 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00005060 * Then fixup all types properties
5061 */
5062 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5063
5064 /*
5065 * Then build the content model for all elements
5066 */
5067 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005068 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005069
5070 /*
5071 * Then check the defaults part of the type like facets values
5072 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005073 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5074 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005075
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005076 if (ctxt->nberrors != 0) {
5077 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005078 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005079 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 return (ret);
5081}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082
Daniel Veillard4255d502002-04-16 15:50:10 +00005083/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00005084 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005085 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005086 * @err: the error callback
5087 * @warn: the warning callback
5088 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005090 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005091 */
5092void
5093xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005094 xmlSchemaValidityErrorFunc err,
5095 xmlSchemaValidityWarningFunc warn, void *ctx)
5096{
Daniel Veillard4255d502002-04-16 15:50:10 +00005097 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005098 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005099 ctxt->error = err;
5100 ctxt->warning = warn;
5101 ctxt->userData = ctx;
5102}
5103
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005104/**
5105 * xmlSchemaFacetTypeToString:
5106 * @type: the facet type
5107 *
5108 * Convert the xmlSchemaTypeType to a char string.
5109 *
5110 * Returns the char string representation of the facet type if the
5111 * type is a facet and an "Internal Error" string otherwise.
5112 */
5113static const char *
5114xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5115{
5116 switch (type) {
5117 case XML_SCHEMA_FACET_PATTERN:
5118 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005119 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005120 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005121 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005122 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005123 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005124 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005125 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005126 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005127 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005128 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005129 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005130 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005131 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005132 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005133 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005134 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005135 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005136 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005137 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005138 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005139 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005140 return ("fractionDigits");
5141 default:
5142 break;
5143 }
5144 return ("Internal Error");
5145}
5146
5147/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005148 * xmlSchemaValidateFacetsInternal:
5149 * @ctxt: a schema validation context
5150 * @base: the base type
5151 * @facets: the list of facets to check
5152 * @value: the lexical repr of the value to validate
5153 * @val: the precomputed value
5154 * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
5155 *
5156 * Check a value against all facet conditions
5157 *
5158 * Returns 0 if the element is schemas valid, a positive error code
5159 * number otherwise and -1 in case of internal or API error.
5160 */
5161static int
5162xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5163 xmlSchemaTypePtr base,
5164 xmlSchemaFacetPtr facets, const xmlChar * value, int fireErrors)
5165{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005166 int ret = 0;
5167 int tmp = 0;
5168 xmlSchemaTypeType type;
5169 xmlSchemaFacetPtr facet = facets;
5170
5171 while (facet != NULL) {
5172 type = facet->type;
5173 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005174 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005175
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005176 while (facet != NULL) {
5177 tmp =
5178 xmlSchemaValidateFacet(base, facet, value,
5179 ctxt->value);
5180 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005181 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005182 }
5183 facet = facet->next;
5184 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005185 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005186 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005187
5188 if (tmp != 0) {
5189 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005190 if (fireErrors)
5191 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 +00005192 }
5193 if (facet != NULL)
5194 facet = facet->next;
5195 }
5196 return (ret);
5197}
5198
William M. Brack87640d52004-04-17 14:58:15 +00005199/**
5200 * xmlSchemaValidateFacets:
5201 * @ctxt: a schema validation context
5202 * @base: the base type
5203 * @facets: the list of facets to check
5204 * @value: the lexical repr of the value to validate
5205 * @val: the precomputed value
5206 *
5207 * Check a value against all facet conditions
5208 *
5209 * Returns 0 if the element is schemas valid, a positive error code
5210 * number otherwise and -1 in case of internal or API error.
5211 */
5212static int
5213xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5214 xmlSchemaTypePtr base,
5215 xmlSchemaFacetPtr facets, const xmlChar * value)
5216{
5217 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5218}
5219
Daniel Veillard4255d502002-04-16 15:50:10 +00005220/************************************************************************
5221 * *
5222 * Simple type validation *
5223 * *
5224 ************************************************************************/
5225
5226/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005227 * xmlSchemaValidateSimpleValueUnion:
5228 * @ctxt: a schema validation context
5229 * @type: the type declaration
5230 * @value: the value to validate
5231 *
5232 * Validates a value against a union.
5233 *
5234 * Returns 0 if the value is valid, a positive error code
5235 * number otherwise and -1 in case of internal or API error.
5236 */
5237static int
5238xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5239 xmlSchemaTypePtr type, const xmlChar * value)
5240{
5241 int ret = 0;
5242 const xmlChar *cur, *end, *prefix, *ncName;
5243 xmlChar *tmp;
5244 xmlSchemaTypePtr subtype;
5245 xmlNsPtr ns;
5246 int len;
5247
5248
5249 /* Process referenced memberTypes. */
5250 cur = type->ref;
5251 do {
5252 while (IS_BLANK_CH(*cur))
5253 cur++;
5254 end = cur;
5255 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5256 end++;
5257 if (end == cur)
5258 break;
5259 tmp = xmlStrndup(cur, end - cur);
5260 ncName = xmlSplitQName3(tmp, &len);
5261 if (ncName != NULL) {
5262 prefix = xmlStrndup(tmp, len);
5263 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5264 } else {
5265 prefix = NULL;
5266 ncName = tmp;
5267 }
5268 /* We won't do additional checks here, since they have been performed during parsing. */
5269 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5270 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5271 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5272 if (tmp != NULL)
5273 xmlFree(tmp);
5274 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00005275 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005276 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5277 if ((ret == 0) || (ret == -1)) {
5278 return (ret);
5279 }
5280 cur = end;
5281 } while (*cur != 0);
5282
5283 if (type->subtypes != NULL) {
5284 subtype = type->subtypes;
5285 do {
5286 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5287 if ((ret == 0) || (ret == -1)) {
5288 return (ret);
5289 }
5290 subtype = subtype->next;
5291 } while (subtype != NULL);
5292 }
5293 return (ret);
5294}
5295
5296/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005297 * xmlSchemaValidateSimpleValue:
5298 * @ctxt: a schema validation context
5299 * @type: the type declaration
5300 * @value: the value to validate
5301 *
5302 * Validate a value against a simple type
5303 *
5304 * Returns 0 if the value is valid, a positive error code
5305 * number otherwise and -1 in case of internal or API error.
5306 */
5307static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005308xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005309 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005310{
Daniel Veillard377e1a92004-04-16 16:30:05 +00005311 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5312}
5313
5314/**
5315 * xmlSchemaValidateSimpleValue:
5316 * @ctxt: a schema validation context
5317 * @type: the type declaration
5318 * @value: the value to validate
5319 * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
5320 *
5321 * Validate a value against a simple type
5322 *
5323 * Returns 0 if the value is valid, a positive error code
5324 * number otherwise and -1 in case of internal or API error.
5325 */
5326static int
5327xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
5328 xmlSchemaTypePtr type, const xmlChar * value, int fireErrors)
5329{
Daniel Veillard4255d502002-04-16 15:50:10 +00005330 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005331
Daniel Veillard4255d502002-04-16 15:50:10 +00005332 /*
5333 * First normalize the value accordingly to Schema Datatype
5334 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5335 */
5336 /*
5337 * Then check the normalized value against the lexical space of the
5338 * type.
5339 */
5340 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005341 if (ctxt->value != NULL) {
5342 xmlSchemaFreeValue(ctxt->value);
5343 ctxt->value = NULL;
5344 }
5345 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5346 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005347 if ((fireErrors) && (ret != 0)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005348 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 +00005349 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005350 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005351 xmlSchemaTypePtr base;
5352 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005353
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005354 base = type->baseType;
5355 if (base != NULL) {
Daniel Veillard377e1a92004-04-16 16:30:05 +00005356 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005357 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005358 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005359 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005360
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005361 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005362 * Do not validate facets or attributes when working on
5363 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005364 */
5365 if (ctxt->schema != NULL) {
5366 if (ret == 0) {
5367 facet = type->facets;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005368 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005369 }
5370 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005371 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005373
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005374 base = type->subtypes;
5375 if (base != NULL) {
Daniel Veillard377e1a92004-04-16 16:30:05 +00005376 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005377 } else {
5378 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005379 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005380 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005381 const xmlChar *cur, *end;
5382 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005383 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005384
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005385 base = type->subtypes;
5386 if (base == NULL) {
5387 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5388 "Internal: List type %s has no base type\n",
5389 type->name, NULL);
5390 return (-1);
5391 }
5392 cur = value;
5393 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005394 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005395 cur++;
5396 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005397 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005398 end++;
5399 if (end == cur)
5400 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005401 tmp = xmlStrndup(cur, end - cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005402 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base, tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005403 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005404 if (ret2 != 0)
5405 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005406 cur = end;
5407 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005408 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
5409 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5410 if ((fireErrors) && (ret != 0)) {
5411 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate type %s\n", type->name, NULL);
5412 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005413 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005414 TODO
5415 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005416 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005417}
5418
5419/************************************************************************
5420 * *
5421 * DOM Validation code *
5422 * *
5423 ************************************************************************/
5424
5425static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005426 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005427static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005428 xmlNodePtr elem,
5429 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005430static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005431 xmlNodePtr elem,
5432 xmlSchemaElementPtr elemDecl,
5433 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005434
5435/**
5436 * xmlSchemaRegisterAttributes:
5437 * @ctxt: a schema validation context
5438 * @attrs: a list of attributes
5439 *
5440 * Register the list of attributes as the set to be validated on that element
5441 *
5442 * Returns -1 in case of error, 0 otherwise
5443 */
5444static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005445xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5446{
Daniel Veillard4255d502002-04-16 15:50:10 +00005447 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005448 if ((attrs->ns != NULL) &&
5449 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5450 attrs = attrs->next;
5451 continue;
5452 }
5453 if (ctxt->attrNr >= ctxt->attrMax) {
5454 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005455
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005456 ctxt->attrMax *= 2;
5457 tmp = (xmlSchemaAttrStatePtr)
5458 xmlRealloc(ctxt->attr, ctxt->attrMax *
5459 sizeof(xmlSchemaAttrState));
5460 if (tmp == NULL) {
5461 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5462 ctxt->attrMax /= 2;
5463 return (-1);
5464 }
5465 ctxt->attr = tmp;
5466 }
5467 ctxt->attr[ctxt->attrNr].attr = attrs;
5468 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5469 ctxt->attrNr++;
5470 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005471 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005472 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005473}
5474
5475/**
5476 * xmlSchemaCheckAttributes:
5477 * @ctxt: a schema validation context
5478 * @node: the node carrying it.
5479 *
5480 * Check that the registered set of attributes on the current node
5481 * has been properly validated.
5482 *
5483 * Returns 0 if validity constraints are met, 1 otherwise.
5484 */
5485static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005486xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5487{
Daniel Veillard4255d502002-04-16 15:50:10 +00005488 int ret = 0;
5489 int i;
5490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005491 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5492 if (ctxt->attr[i].attr == NULL)
5493 break;
5494 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5495 ret = 1;
5496 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5497 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005498 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005499 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005500}
5501
5502/**
5503 * xmlSchemaValidateSimpleContent:
5504 * @ctxt: a schema validation context
5505 * @elem: an element
5506 * @type: the type declaration
5507 *
5508 * Validate the content of an element expected to be a simple type
5509 *
5510 * Returns 0 if the element is schemas valid, a positive error code
5511 * number otherwise and -1 in case of internal or API error.
5512 */
5513static int
5514xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005515 xmlNodePtr node ATTRIBUTE_UNUSED)
5516{
Daniel Veillard4255d502002-04-16 15:50:10 +00005517 xmlNodePtr child;
5518 xmlSchemaTypePtr type, base;
5519 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005520 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005521
5522 child = ctxt->node;
5523 type = ctxt->type;
5524
5525 /*
5526 * Validation Rule: Element Locally Valid (Type): 3.1.3
5527 */
5528 value = xmlNodeGetContent(child);
5529 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5530 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005531 case XML_SCHEMA_TYPE_RESTRICTION:{
5532 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005533
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005534 base = type->baseType;
5535 if (base != NULL) {
5536 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5537 } else {
5538 TODO}
5539 if (ret == 0) {
5540 facet = type->facets;
5541 ret =
5542 xmlSchemaValidateFacets(ctxt, base, facet, value);
5543 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005544 if ((ret == 0) && (type->attributes != NULL)) {
5545 ret = xmlSchemaValidateAttributes(ctxt, node,
5546 type->attributes);
5547 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005548 break;
5549 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005550 case XML_SCHEMA_TYPE_EXTENSION:{
5551 TODO
5552 break;
5553 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005554 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005555 TODO
5556 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005557 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005558 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005559
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005560 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005561}
5562
5563/**
5564 * xmlSchemaValidateCheckNodeList
5565 * @nodelist: the list of nodes
5566 *
5567 * Check the node list is only made of text nodes and entities pointing
5568 * to text nodes
5569 *
5570 * Returns 1 if true, 0 if false and -1 in case of error
5571 */
5572static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005573xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5574{
Daniel Veillard4255d502002-04-16 15:50:10 +00005575 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005576 if (nodelist->type == XML_ENTITY_REF_NODE) {
5577 TODO /* implement recursion in the entity content */
5578 }
5579 if ((nodelist->type != XML_TEXT_NODE) &&
5580 (nodelist->type != XML_COMMENT_NODE) &&
5581 (nodelist->type != XML_PI_NODE) &&
5582 (nodelist->type != XML_PI_NODE)) {
5583 return (0);
5584 }
5585 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005586 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005587 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005588}
5589
5590/**
5591 * xmlSchemaSkipIgnored:
5592 * @ctxt: a schema validation context
5593 * @type: the current type context
5594 * @node: the top node.
5595 *
5596 * Skip ignorable nodes in that context
5597 *
5598 * Returns the new sibling
5599 * number otherwise and -1 in case of internal or API error.
5600 */
5601static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005602xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005603 xmlSchemaTypePtr type, xmlNodePtr node)
5604{
Daniel Veillard4255d502002-04-16 15:50:10 +00005605 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005606
Daniel Veillard4255d502002-04-16 15:50:10 +00005607 /*
5608 * TODO complete and handle entities
5609 */
5610 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005611 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005612 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005613 ((node->type == XML_COMMENT_NODE) ||
5614 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5615 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5616 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5617 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005618 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005619 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005620}
5621
5622/**
5623 * xmlSchemaValidateCallback:
5624 * @ctxt: a schema validation context
5625 * @name: the name of the element detected (might be NULL)
5626 * @type: the type
5627 *
5628 * A transition has been made in the automata associated to an element
5629 * content model
5630 */
5631static void
5632xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 const xmlChar * name ATTRIBUTE_UNUSED,
5634 xmlSchemaTypePtr type, xmlNodePtr node)
5635{
Daniel Veillard4255d502002-04-16 15:50:10 +00005636 xmlSchemaTypePtr oldtype = ctxt->type;
5637 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005638
Daniel Veillard4255d502002-04-16 15:50:10 +00005639#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005640 xmlGenericError(xmlGenericErrorContext,
5641 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005643#endif
5644 ctxt->type = type;
5645 ctxt->node = node;
5646 xmlSchemaValidateContent(ctxt, node);
5647 ctxt->type = oldtype;
5648 ctxt->node = oldnode;
5649}
5650
5651
5652#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005653
Daniel Veillard4255d502002-04-16 15:50:10 +00005654/**
5655 * xmlSchemaValidateSimpleRestrictionType:
5656 * @ctxt: a schema validation context
5657 * @node: the top node.
5658 *
5659 * Validate the content of a restriction type.
5660 *
5661 * Returns 0 if the element is schemas valid, a positive error code
5662 * number otherwise and -1 in case of internal or API error.
5663 */
5664static int
5665xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5666 xmlNodePtr node)
5667{
5668 xmlNodePtr child;
5669 xmlSchemaTypePtr type;
5670 int ret;
5671
5672 child = ctxt->node;
5673 type = ctxt->type;
5674
5675 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005676 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005677 return (-1);
5678 }
5679 /*
5680 * Only text and text based entities references shall be found there
5681 */
5682 ret = xmlSchemaValidateCheckNodeList(child);
5683 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005684 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005685 return (-1);
5686 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005687 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 +00005688 return (-1);
5689 }
5690 ctxt->type = type->subtypes;
5691 xmlSchemaValidateContent(ctxt, node);
5692 ctxt->type = type;
5693 return (ret);
5694}
5695#endif
5696
5697/**
5698 * xmlSchemaValidateSimpleType:
5699 * @ctxt: a schema validation context
5700 * @node: the top node.
5701 *
5702 * Validate the content of an simple type.
5703 *
5704 * Returns 0 if the element is schemas valid, a positive error code
5705 * number otherwise and -1 in case of internal or API error.
5706 */
5707static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005708xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5709{
Daniel Veillard4255d502002-04-16 15:50:10 +00005710 xmlNodePtr child;
5711 xmlSchemaTypePtr type;
5712 xmlAttrPtr attr;
5713 int ret;
5714
5715 child = ctxt->node;
5716 type = ctxt->type;
5717
5718 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005719 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5720 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005721 }
5722 /*
5723 * Only text and text based entities references shall be found there
5724 */
5725 ret = xmlSchemaValidateCheckNodeList(child);
5726 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005727 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5728 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005729 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005730 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5731 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005732 }
5733 /*
5734 * Validation Rule: Element Locally Valid (Type): 3.1.1
5735 */
5736 attr = node->properties;
5737 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005738 if ((attr->ns == NULL) ||
5739 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5740 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5741 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5742 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5743 (!xmlStrEqual
5744 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5745 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5746 return (ctxt->err);
5747 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005748 }
5749
5750 ctxt->type = type->subtypes;
5751 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5752 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005753 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005754}
5755
5756/**
5757 * xmlSchemaValidateElementType:
5758 * @ctxt: a schema validation context
5759 * @node: the top node.
5760 *
5761 * Validate the content of an element type.
5762 * Validation Rule: Element Locally Valid (Complex Type)
5763 *
5764 * Returns 0 if the element is schemas valid, a positive error code
5765 * number otherwise and -1 in case of internal or API error.
5766 */
5767static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005768xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5769{
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 xmlNodePtr child;
5771 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005772 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005773 xmlSchemaElementPtr decl;
5774 int ret, attrBase;
5775
5776 oldregexp = ctxt->regexp;
5777
5778 child = ctxt->node;
5779 type = ctxt->type;
5780
5781 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005782 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5783 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005784 }
5785 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005786 if (type->minOccurs > 0) {
5787 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5788 }
5789 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005790 }
5791
5792 /*
5793 * Verify the element matches
5794 */
5795 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5797 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005798 }
5799 /*
5800 * Verify the attributes
5801 */
5802 attrBase = ctxt->attrBase;
5803 ctxt->attrBase = ctxt->attrNr;
5804 xmlSchemaRegisterAttributes(ctxt, child->properties);
5805 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5806 /*
5807 * Verify the element content recursively
5808 */
5809 decl = (xmlSchemaElementPtr) type;
5810 oldregexp = ctxt->regexp;
5811 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5813 (xmlRegExecCallbacks)
5814 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005815#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005817#endif
5818 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005819 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5820 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005821
5822 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005823 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005824#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005825 xmlGenericError(xmlGenericErrorContext,
5826 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005827#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 if (ret == 0) {
5829 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5830 } else if (ret < 0) {
5831 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005832#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005833 } else {
5834 xmlGenericError(xmlGenericErrorContext,
5835 "Element %s content check succeeded\n",
5836 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005837
5838#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005839 }
5840 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005841 }
5842 /*
5843 * Verify that all attributes were Schemas-validated
5844 */
5845 xmlSchemaCheckAttributes(ctxt, node);
5846 ctxt->attrNr = ctxt->attrBase;
5847 ctxt->attrBase = attrBase;
5848
5849 ctxt->regexp = oldregexp;
5850
5851 ctxt->node = child;
5852 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005853 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005854}
5855
5856/**
5857 * xmlSchemaValidateBasicType:
5858 * @ctxt: a schema validation context
5859 * @node: the top node.
5860 *
5861 * Validate the content of an element expected to be a basic type type
5862 *
5863 * Returns 0 if the element is schemas valid, a positive error code
5864 * number otherwise and -1 in case of internal or API error.
5865 */
5866static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005867xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5868{
Daniel Veillard4255d502002-04-16 15:50:10 +00005869 int ret;
5870 xmlNodePtr child, cur;
5871 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005872 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005873
5874 child = ctxt->node;
5875 type = ctxt->type;
5876
5877 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005878 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5879 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005880 }
5881 /*
5882 * First check the content model of the node.
5883 */
5884 cur = child;
5885 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005886 switch (cur->type) {
5887 case XML_TEXT_NODE:
5888 case XML_CDATA_SECTION_NODE:
5889 case XML_PI_NODE:
5890 case XML_COMMENT_NODE:
5891 case XML_XINCLUDE_START:
5892 case XML_XINCLUDE_END:
5893 break;
5894 case XML_ENTITY_REF_NODE:
5895 case XML_ENTITY_NODE:
5896 TODO break;
5897 case XML_ELEMENT_NODE:
5898 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5899 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005900 case XML_ATTRIBUTE_NODE:
5901 case XML_DOCUMENT_NODE:
5902 case XML_DOCUMENT_TYPE_NODE:
5903 case XML_DOCUMENT_FRAG_NODE:
5904 case XML_NOTATION_NODE:
5905 case XML_HTML_DOCUMENT_NODE:
5906 case XML_DTD_NODE:
5907 case XML_ELEMENT_DECL:
5908 case XML_ATTRIBUTE_DECL:
5909 case XML_ENTITY_DECL:
5910 case XML_NAMESPACE_DECL:
5911#ifdef LIBXML_DOCB_ENABLED
5912 case XML_DOCB_DOCUMENT_NODE:
5913#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005914 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5915 return (ctxt->err);
5916 }
5917 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005918 }
5919 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005920 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005921 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005922 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005923
5924 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005925 xmlSchemaFreeValue(ctxt->value);
5926 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005927 }
5928 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5929 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005930 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005931 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005932 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 +00005933 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005934 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005935}
5936
5937/**
5938 * xmlSchemaValidateComplexType:
5939 * @ctxt: a schema validation context
5940 * @node: the top node.
5941 *
5942 * Validate the content of an element expected to be a complex type type
5943 * xmlschema-1.html#cvc-complex-type
5944 * Validation Rule: Element Locally Valid (Complex Type)
5945 *
5946 * Returns 0 if the element is schemas valid, a positive error code
5947 * number otherwise and -1 in case of internal or API error.
5948 */
5949static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005950xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5951{
Daniel Veillard4255d502002-04-16 15:50:10 +00005952 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005953 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005954 int ret;
5955
5956 child = ctxt->node;
5957 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005958 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005959
Daniel Veillard4255d502002-04-16 15:50:10 +00005960 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005961 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005962 if (type->baseType != NULL) {
5963 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005964 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5965 }
5966 if (type->attributes != NULL) {
5967 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5968 }
5969 subtype = type->subtypes;
5970 while (subtype != NULL) {
5971 ctxt->type = subtype;
5972 xmlSchemaValidateComplexType(ctxt, node);
5973 subtype = subtype->next;
5974 }
5975 break;
5976 case XML_SCHEMA_CONTENT_ELEMENTS:
5977 case XML_SCHEMA_CONTENT_MIXED:
5978 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5979 /*
5980 * Skip ignorable nodes in that context
5981 */
5982 child = xmlSchemaSkipIgnored(ctxt, type, child);
5983 while (child != NULL) {
5984 if (child->type == XML_ELEMENT_NODE) {
5985 ret = xmlRegExecPushString(ctxt->regexp,
5986 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005987#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005988 if (ret < 0)
5989 xmlGenericError(xmlGenericErrorContext,
5990 " --> %s Error\n", child->name);
5991 else
5992 xmlGenericError(xmlGenericErrorContext,
5993 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005994#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005995 }
5996 child = child->next;
5997 /*
5998 * Skip ignorable nodes in that context
5999 */
6000 child = xmlSchemaSkipIgnored(ctxt, type, child);
6001 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00006002 if (type->attributes != NULL) {
6003 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6004 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006005 break;
6006 case XML_SCHEMA_CONTENT_BASIC:{
6007 if (type->subtypes != NULL) {
6008 ctxt->type = type->subtypes;
6009 xmlSchemaValidateComplexType(ctxt, node);
6010 }
6011 if (type->baseType != NULL) {
6012 ctxt->type = type->baseType;
6013 xmlSchemaValidateBasicType(ctxt, node);
6014 }
6015 if (type->attributes != NULL) {
6016 xmlSchemaValidateAttributes(ctxt, node,
6017 type->attributes);
6018 }
6019 ctxt->type = type;
6020 break;
6021 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006022 case XML_SCHEMA_CONTENT_SIMPLE:{
6023 if (type->subtypes != NULL) {
6024 ctxt->type = type->subtypes;
6025 xmlSchemaValidateComplexType(ctxt, node);
6026 }
6027 if (type->baseType != NULL) {
6028 ctxt->type = type->baseType;
6029 xmlSchemaValidateComplexType(ctxt, node);
6030 }
6031 if (type->attributes != NULL) {
6032 xmlSchemaValidateAttributes(ctxt, node,
6033 type->attributes);
6034 }
6035 ctxt->type = type;
6036 break;
6037 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038 default:
6039 TODO xmlGenericError(xmlGenericErrorContext,
6040 "unimplemented content type %d\n",
6041 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006042 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006043 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006044}
6045
6046/**
6047 * xmlSchemaValidateContent:
6048 * @ctxt: a schema validation context
6049 * @elem: an element
6050 * @type: the type declaration
6051 *
6052 * Validate the content of an element against the type.
6053 *
6054 * Returns 0 if the element is schemas valid, a positive error code
6055 * number otherwise and -1 in case of internal or API error.
6056 */
6057static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006058xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6059{
Daniel Veillard4255d502002-04-16 15:50:10 +00006060 xmlNodePtr child;
6061 xmlSchemaTypePtr type;
6062
6063 child = ctxt->node;
6064 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006065 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006066
Daniel Veillarde19fc232002-04-22 16:01:24 +00006067 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006068 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00006069
Daniel Veillard4255d502002-04-16 15:50:10 +00006070 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006071 case XML_SCHEMA_TYPE_ANY:
6072 /* Any type will do it, fine */
6073 TODO /* handle recursivity */
6074 break;
6075 case XML_SCHEMA_TYPE_COMPLEX:
6076 xmlSchemaValidateComplexType(ctxt, node);
6077 break;
6078 case XML_SCHEMA_TYPE_ELEMENT:{
6079 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6080
6081 /*
6082 * Handle element reference here
6083 */
6084 if (decl->ref != NULL) {
6085 if (decl->refDecl == NULL) {
6086 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
6087 return (-1);
6088 }
6089 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6090 decl = decl->refDecl;
6091 }
6092 xmlSchemaValidateElementType(ctxt, node);
6093 ctxt->type = type;
6094 break;
6095 }
6096 case XML_SCHEMA_TYPE_BASIC:
6097 xmlSchemaValidateBasicType(ctxt, node);
6098 break;
6099 case XML_SCHEMA_TYPE_FACET:
6100 TODO break;
6101 case XML_SCHEMA_TYPE_SIMPLE:
6102 xmlSchemaValidateSimpleType(ctxt, node);
6103 break;
6104 case XML_SCHEMA_TYPE_SEQUENCE:
6105 TODO break;
6106 case XML_SCHEMA_TYPE_CHOICE:
6107 TODO break;
6108 case XML_SCHEMA_TYPE_ALL:
6109 TODO break;
6110 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6111 TODO break;
6112 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6113 TODO break;
6114 case XML_SCHEMA_TYPE_UR:
6115 TODO break;
6116 case XML_SCHEMA_TYPE_RESTRICTION:
6117 /*xmlSchemaValidateRestrictionType(ctxt, node); */
6118 TODO break;
6119 case XML_SCHEMA_TYPE_EXTENSION:
6120 TODO break;
6121 case XML_SCHEMA_TYPE_ATTRIBUTE:
6122 TODO break;
6123 case XML_SCHEMA_TYPE_GROUP:
6124 TODO break;
6125 case XML_SCHEMA_TYPE_NOTATION:
6126 TODO break;
6127 case XML_SCHEMA_TYPE_LIST:
6128 TODO break;
6129 case XML_SCHEMA_TYPE_UNION:
6130 TODO break;
6131 case XML_SCHEMA_FACET_MININCLUSIVE:
6132 TODO break;
6133 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6134 TODO break;
6135 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6136 TODO break;
6137 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6138 TODO break;
6139 case XML_SCHEMA_FACET_TOTALDIGITS:
6140 TODO break;
6141 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6142 TODO break;
6143 case XML_SCHEMA_FACET_PATTERN:
6144 TODO break;
6145 case XML_SCHEMA_FACET_ENUMERATION:
6146 TODO break;
6147 case XML_SCHEMA_FACET_WHITESPACE:
6148 TODO break;
6149 case XML_SCHEMA_FACET_LENGTH:
6150 TODO break;
6151 case XML_SCHEMA_FACET_MAXLENGTH:
6152 TODO break;
6153 case XML_SCHEMA_FACET_MINLENGTH:
6154 TODO break;
6155 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6156 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00006157 }
6158 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6159
6160 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006161 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006162 ctxt->node = ctxt->node->next;
6163 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006164 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006165}
6166
6167/**
6168 * xmlSchemaValidateType:
6169 * @ctxt: a schema validation context
6170 * @elem: an element
6171 * @type: the list of type declarations
6172 *
6173 * Validate the content of an element against the types.
6174 *
6175 * Returns 0 if the element is schemas valid, a positive error code
6176 * number otherwise and -1 in case of internal or API error.
6177 */
6178static int
6179xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006180 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6181{
Daniel Veillard4255d502002-04-16 15:50:10 +00006182 xmlChar *nil;
6183
Daniel Veillard2db8c122003-07-08 12:16:59 +00006184 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006185 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00006186
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 /*
6188 * 3.3.4 : 2
6189 */
6190 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006191 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
6192 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006193 }
6194 /*
6195 * 3.3.4: 3
6196 */
6197 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6198 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006199 /* 3.3.4: 3.2 */
6200 if (xmlStrEqual(nil, BAD_CAST "true")) {
6201 if (elem->children != NULL) {
6202 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
6203 return (ctxt->err);
6204 }
6205 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6206 (elemDecl->value != NULL)) {
6207 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
6208 return (ctxt->err);
6209 }
6210 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006211 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006212 /* 3.3.4: 3.1 */
6213 if (nil != NULL) {
6214 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
6215 xmlFree(nil);
6216 return (ctxt->err);
6217 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006218 }
6219
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006220 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006221
6222 ctxt->type = elemDecl->subtypes;
6223 ctxt->node = elem->children;
6224 xmlSchemaValidateContent(ctxt, elem);
6225 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006226
6227 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006228}
6229
6230
6231/**
6232 * xmlSchemaValidateAttributes:
6233 * @ctxt: a schema validation context
6234 * @elem: an element
6235 * @attributes: the list of attribute declarations
6236 *
6237 * Validate the attributes of an element.
6238 *
6239 * Returns 0 if the element is schemas valid, a positive error code
6240 * number otherwise and -1 in case of internal or API error.
6241 */
6242static int
6243xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006244 xmlSchemaAttributePtr attributes)
6245{
William M. Brack87640d52004-04-17 14:58:15 +00006246 int i, ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006247 xmlAttrPtr attr;
6248 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006249 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006250 int found;
Daniel Veillard4255d502002-04-16 15:50:10 +00006251
6252 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006253 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006254 while (attributes != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006255 found = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006256 /*
6257 * Handle attribute groups
6258 */
6259 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6260 group = (xmlSchemaAttributeGroupPtr) attributes;
6261 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6262 attributes = group->next;
6263 continue;
6264 }
6265 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6266 attr = ctxt->attr[i].attr;
6267 if (attr == NULL)
6268 continue;
6269 if (attributes->ref != NULL) {
6270 if (!xmlStrEqual(attr->name, attributes->ref))
6271 continue;
6272 if (attr->ns != NULL) {
6273 if ((attributes->refNs == NULL) ||
6274 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6275 continue;
6276 } else if (attributes->refNs != NULL) {
6277 continue;
6278 }
6279 } else {
6280 if (!xmlStrEqual(attr->name, attributes->name))
6281 continue;
6282 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006283 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006284 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006285 if (attr->ns == NULL) {
6286 /*
6287 * accept an unqualified attribute only if the declaration
6288 * is unqualified or if the schemas allowed it.
6289 */
6290 if ((attributes->targetNamespace != NULL) &&
6291 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6292 continue;
6293 } else {
6294 if (attributes->targetNamespace == NULL)
6295 continue;
6296 if (!xmlStrEqual(attributes->targetNamespace,
6297 attr->ns->href))
6298 continue;
6299 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006300 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006301 found = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006302 ctxt->cur = (xmlNodePtr) attributes;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006303
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006304 if (attributes->subtypes == NULL) {
6305 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6306 continue;
6307 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006308
6309 if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6310 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR, "attribute %s on %s is prohibited\n", attributes->name, elem->name);
6311 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems not very logical but it
6312 surpresses the "attribute is unknown" error report. Please change this if you know better */
6313 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6314 break;
6315 }
6316
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006317 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6318 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6319 value);
6320 if (ret != 0) {
6321 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6322 } else {
6323 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6324 }
6325 if (value != NULL) {
6326 xmlFree(value);
6327 }
6328 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006329 if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6330 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING, "required attribute %s on %s is missing\n", attributes->name, elem->name);
6331 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006332 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006333 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006334 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006335}
6336
6337/**
6338 * xmlSchemaValidateElement:
6339 * @ctxt: a schema validation context
6340 * @elem: an element
6341 *
6342 * Validate an element in a tree
6343 *
6344 * Returns 0 if the element is schemas valid, a positive error code
6345 * number otherwise and -1 in case of internal or API error.
6346 */
6347static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006348xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6349{
Daniel Veillard4255d502002-04-16 15:50:10 +00006350 xmlSchemaElementPtr elemDecl;
6351 int ret, attrBase;
6352
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006353 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006354 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6355 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006356 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006357 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6358 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006359 }
6360 /*
6361 * special case whe elementFormDefault is unqualified for top-level elem.
6362 */
6363 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6364 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6365 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6366 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6367 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6368 elem->name, NULL, NULL);
6369 }
6370
Daniel Veillard4255d502002-04-16 15:50:10 +00006371 /*
6372 * 3.3.4 : 1
6373 */
6374 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006375 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6376 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006377 }
6378 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006379 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6380 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006381 }
6382 /*
6383 * Verify the attributes
6384 */
6385 attrBase = ctxt->attrBase;
6386 ctxt->attrBase = ctxt->attrNr;
6387 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6388 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6389 /*
6390 * Verify the element content recursively
6391 */
6392 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006393 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6394 (xmlRegExecCallbacks)
6395 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006396#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006397 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006398#endif
6399 }
6400 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006401 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006402 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006403#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006404 xmlGenericError(xmlGenericErrorContext,
6405 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006406#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006407 if (ret == 0) {
6408 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6409 } else if (ret < 0) {
6410 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006411#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006412 } else {
6413 xmlGenericError(xmlGenericErrorContext,
6414 "Element %s content check succeeded\n",
6415 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006416
6417#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006418 }
6419 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006420 }
6421 /*
6422 * Verify that all attributes were Schemas-validated
6423 */
6424 xmlSchemaCheckAttributes(ctxt, elem);
6425 ctxt->attrNr = ctxt->attrBase;
6426 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006427
6428 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006429}
6430
6431/**
6432 * xmlSchemaValidateDocument:
6433 * @ctxt: a schema validation context
6434 * @doc: a parsed document tree
6435 *
6436 * Validate a document tree in memory.
6437 *
6438 * Returns 0 if the document is schemas valid, a positive error code
6439 * number otherwise and -1 in case of internal or API error.
6440 */
6441static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006442xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6443{
Daniel Veillard4255d502002-04-16 15:50:10 +00006444 xmlNodePtr root;
6445 xmlSchemaElementPtr elemDecl;
6446
6447 root = xmlDocGetRootElement(doc);
6448 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006449 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6450 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006451 }
6452 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006453 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6454 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006455 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006456 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6457 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006458 /*
6459 * special case whe elementFormDefault is unqualified for top-level elem.
6460 */
6461 if ((elemDecl == NULL) && (root->ns != NULL) &&
6462 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6463 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6464 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6465 root->name, NULL, NULL);
6466 }
6467
Daniel Veillard4255d502002-04-16 15:50:10 +00006468 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006469 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006470 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006471 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006472 }
6473 /*
6474 * Okay, start the recursive validation
6475 */
6476 xmlSchemaValidateElement(ctxt, root);
6477
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006478 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006479}
6480
6481/************************************************************************
6482 * *
6483 * SAX Validation code *
6484 * *
6485 ************************************************************************/
6486
6487/************************************************************************
6488 * *
6489 * Validation interfaces *
6490 * *
6491 ************************************************************************/
6492
6493/**
6494 * xmlSchemaNewValidCtxt:
6495 * @schema: a precompiled XML Schemas
6496 *
6497 * Create an XML Schemas validation context based on the given schema
6498 *
6499 * Returns the validation context or NULL in case of error
6500 */
6501xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006502xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6503{
Daniel Veillard4255d502002-04-16 15:50:10 +00006504 xmlSchemaValidCtxtPtr ret;
6505
6506 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6507 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006508 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006509 return (NULL);
6510 }
6511 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6512 ret->schema = schema;
6513 ret->attrNr = 0;
6514 ret->attrMax = 10;
6515 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006516 sizeof
6517 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006518 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006519 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6520 free(ret);
6521 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006522 }
6523 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6524 return (ret);
6525}
6526
6527/**
6528 * xmlSchemaFreeValidCtxt:
6529 * @ctxt: the schema validation context
6530 *
6531 * Free the resources associated to the schema validation context
6532 */
6533void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006534xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6535{
Daniel Veillard4255d502002-04-16 15:50:10 +00006536 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006537 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006538 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006539 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006540 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006541 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006542 xmlFree(ctxt);
6543}
6544
6545/**
6546 * xmlSchemaSetValidErrors:
6547 * @ctxt: a schema validation context
6548 * @err: the error function
6549 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006550 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006551 *
6552 * Set the error and warning callback informations
6553 */
6554void
6555xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006556 xmlSchemaValidityErrorFunc err,
6557 xmlSchemaValidityWarningFunc warn, void *ctx)
6558{
Daniel Veillard4255d502002-04-16 15:50:10 +00006559 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006560 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006561 ctxt->error = err;
6562 ctxt->warning = warn;
6563 ctxt->userData = ctx;
6564}
6565
6566/**
6567 * xmlSchemaValidateDoc:
6568 * @ctxt: a schema validation context
6569 * @doc: a parsed document tree
6570 *
6571 * Validate a document tree in memory.
6572 *
6573 * Returns 0 if the document is schemas valid, a positive error code
6574 * number otherwise and -1 in case of internal or API error.
6575 */
6576int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006577xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6578{
Daniel Veillard4255d502002-04-16 15:50:10 +00006579 int ret;
6580
6581 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006582 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006583
6584 ctxt->doc = doc;
6585 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006586 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006587}
6588
6589/**
6590 * xmlSchemaValidateStream:
6591 * @ctxt: a schema validation context
6592 * @input: the input to use for reading the data
6593 * @enc: an optional encoding information
6594 * @sax: a SAX handler for the resulting events
6595 * @user_data: the context to provide to the SAX handler.
6596 *
6597 * Validate a document tree in memory.
6598 *
6599 * Returns 0 if the document is schemas valid, a positive error code
6600 * number otherwise and -1 in case of internal or API error.
6601 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006602int
Daniel Veillard4255d502002-04-16 15:50:10 +00006603xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006604 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6605 xmlSAXHandlerPtr sax, void *user_data)
6606{
Daniel Veillard4255d502002-04-16 15:50:10 +00006607 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006608 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006609 ctxt->input = input;
6610 ctxt->enc = enc;
6611 ctxt->sax = sax;
6612 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006613 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006614}
6615
6616#endif /* LIBXML_SCHEMAS_ENABLED */