blob: bdd7826c7dd984d670b24cc97554887f5ac41b5c [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
Daniel Veillardf7627552004-04-22 07:15:40 +00004241 if (type->recurse) {
4242 xmlSchemaPErr(ctxt, type->node,
4243 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4244 "Schemas: extension type %s is recursive\n",
4245 type->name, NULL);
4246 return;
4247 }
4248 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004249 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00004250 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004251 subtypes = type->subtypes;
4252 while (subtypes != NULL) {
4253 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4254 subtypes = subtypes->next;
4255 }
4256 } else if (type->subtypes != NULL)
4257 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4258 break;
4259 case XML_SCHEMA_TYPE_GROUP:
4260 if (type->subtypes == NULL) {
4261 }
4262 case XML_SCHEMA_TYPE_COMPLEX:
4263 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4264 if (type->subtypes != NULL)
4265 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4266 break;
4267 default:
4268 xmlGenericError(xmlGenericErrorContext,
4269 "Found unexpected type %d in %s content model\n",
4270 type->type, name);
4271 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004272 }
4273}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004274
Daniel Veillard4255d502002-04-16 15:50:10 +00004275/**
4276 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004277 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004278 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004279 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004281 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004282 */
4283static void
4284xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004285 xmlSchemaParserCtxtPtr ctxt,
4286 const xmlChar * name)
4287{
Daniel Veillard4255d502002-04-16 15:50:10 +00004288 xmlAutomataStatePtr start;
4289
Daniel Veillard4255d502002-04-16 15:50:10 +00004290 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004291 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004292 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004293 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4294 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004295 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004296 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004297 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004298 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4299 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004300 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004301
4302#ifdef DEBUG_CONTENT
4303 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004304 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004305#endif
4306
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 ctxt->am = xmlNewAutomata();
4308 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 xmlGenericError(xmlGenericErrorContext,
4310 "Cannot create automata for elem %s\n", name);
4311 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004312 }
4313 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4314 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4315 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004316 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004317 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004318 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4319 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004320 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004321 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4322 "Content model of %s is not determinist:\n", name,
4323 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004324 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004325#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004326 xmlGenericError(xmlGenericErrorContext,
4327 "Content model of %s:\n", name);
4328 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004329#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004330 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004331 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004332 xmlFreeAutomata(ctxt->am);
4333 ctxt->am = NULL;
4334}
4335
4336/**
4337 * xmlSchemaRefFixupCallback:
4338 * @elem: the schema element context
4339 * @ctxt: the schema parser context
4340 *
4341 * Free the resources associated to the schema parser context
4342 */
4343static void
4344xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004345 xmlSchemaParserCtxtPtr ctxt,
4346 const xmlChar * name,
4347 const xmlChar * context ATTRIBUTE_UNUSED,
4348 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004349{
4350 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004351 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004352 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004353 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004354
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004355 if (elem->subtypes != NULL) {
4356 xmlSchemaPErr(ctxt, elem->node,
4357 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4358 "Schemas: element %s have both ref and subtype\n",
4359 name, NULL);
4360 return;
4361 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004362 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004363
4364 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004365 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4366 "Schemas: element %s ref to %s not found\n",
4367 name, elem->ref);
4368 return;
4369 }
4370 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004371 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004372 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004373
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004374 if (elem->subtypes != NULL) {
4375 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4376 "Schemas: element %s have both type and subtype\n",
4377 name, NULL);
4378 return;
4379 }
4380 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4381 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004382
4383 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004384 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4385 "Schemas: element %s type %s not found\n", name,
4386 elem->namedType);
4387 return;
4388 }
4389 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 }
4391}
4392
Daniel Veillard377e1a92004-04-16 16:30:05 +00004393static void
4394xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr typeDecl,
4395 xmlSchemaParserCtxtPtr ctxt)
4396{
4397 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
4398 xmlChar *tmp;
4399 xmlSchemaTypePtr subtype;
4400 xmlNsPtr ns;
4401 int len;
4402
4403 if ((typeDecl->type != XML_SCHEMA_TYPE_UNION) || (typeDecl->ref == NULL))
4404 return;
4405
4406 cur = typeDecl->ref;
4407 do {
4408 while (IS_BLANK_CH(*cur))
4409 cur++;
4410 end = cur;
4411 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4412 end++;
4413 if (end == cur)
4414 break;
4415 tmp = xmlStrndup(cur, end - cur);
4416 ncName = xmlSplitQName3(tmp, &len);
4417 if (ncName != NULL) {
4418 prefix = xmlDictLookup(ctxt->dict, tmp, len);
4419 } else {
4420 prefix = NULL;
4421 ncName = tmp;
4422 }
4423 ns = xmlSearchNs(typeDecl->node->doc, typeDecl->node, prefix);
4424 if (ns == NULL) {
4425 xmlSchemaPErr(ctxt, typeDecl->node, XML_SCHEMAP_PREFIX_UNDEFINED,
4426 "Union %s: the namespace of member type %s is undefined\n",
William M. Brack87640d52004-04-17 14:58:15 +00004427 typeDecl->name, (const xmlChar *) tmp);
4428 namespace = NULL;
Daniel Veillard377e1a92004-04-16 16:30:05 +00004429 } else {
4430 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4431 }
4432 /* Lookup the referenced type */
4433 subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
4434 if (subtype == NULL) {
4435 xmlSchemaPErr(ctxt, typeDecl->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
4436 "Union %s references an unknown member type >%s<\n",
William M. Brack87640d52004-04-17 14:58:15 +00004437 typeDecl->name, (const xmlChar *) tmp);
Daniel Veillard377e1a92004-04-16 16:30:05 +00004438 }
4439 xmlFree(tmp);
4440 cur = end;
4441 } while (*cur != 0);
4442
4443}
4444
Daniel Veillard4255d502002-04-16 15:50:10 +00004445/**
4446 * xmlSchemaTypeFixup:
4447 * @typeDecl: the schema type definition
4448 * @ctxt: the schema parser context
4449 *
4450 * Fixes the content model of the type.
4451 */
4452static void
4453xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004454 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004455{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004456 if (typeDecl == NULL)
4457 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004459 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004460 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004461 switch (typeDecl->type) {
4462 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4463 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4464 if (typeDecl->subtypes != NULL)
4465 typeDecl->contentType =
4466 typeDecl->subtypes->contentType;
4467 break;
4468 }
4469 case XML_SCHEMA_TYPE_RESTRICTION:{
4470 if (typeDecl->subtypes != NULL)
4471 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004472
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004473 if (typeDecl->base != NULL) {
4474 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004475
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004476 baseType =
4477 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4478 typeDecl->baseNs);
4479 if (baseType == NULL) {
4480 xmlSchemaPErr(ctxt, typeDecl->node,
4481 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004482 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004483 name, typeDecl->base);
4484 }
4485 typeDecl->baseType = baseType;
4486 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004487 if (typeDecl->subtypes == NULL)
4488 if (typeDecl->baseType != NULL)
4489 typeDecl->contentType =
4490 typeDecl->baseType->contentType;
4491 else
4492 /* 1.1.1 */
4493 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004494 else if ((typeDecl->subtypes->subtypes == NULL) &&
4495 ((typeDecl->subtypes->type ==
4496 XML_SCHEMA_TYPE_ALL)
4497 || (typeDecl->subtypes->type ==
4498 XML_SCHEMA_TYPE_SEQUENCE)))
4499 /* 1.1.2 */
4500 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4501 else if ((typeDecl->subtypes->type ==
4502 XML_SCHEMA_TYPE_CHOICE)
4503 && (typeDecl->subtypes->subtypes == NULL))
4504 /* 1.1.3 */
4505 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4506 else {
4507 /* 1.2 and 2.X are applied at the other layer */
4508 typeDecl->contentType =
4509 XML_SCHEMA_CONTENT_ELEMENTS;
4510 }
4511 break;
4512 }
4513 case XML_SCHEMA_TYPE_EXTENSION:{
4514 xmlSchemaContentType explicitContentType;
4515 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004516
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004517 if (typeDecl->base != NULL) {
4518 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004519
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520 baseType =
4521 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4522 typeDecl->baseNs);
4523 if (baseType == NULL) {
4524 xmlSchemaPErr(ctxt, typeDecl->node,
4525 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004526 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004527 name, typeDecl->base);
4528 }
4529 typeDecl->baseType = baseType;
4530 }
4531 if (typeDecl->subtypes != NULL)
4532 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004533
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004534 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4535 if (typeDecl->subtypes == NULL)
4536 /* 1.1.1 */
4537 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4538 else if ((typeDecl->subtypes->subtypes == NULL) &&
4539 ((typeDecl->subtypes->type ==
4540 XML_SCHEMA_TYPE_ALL)
4541 || (typeDecl->subtypes->type ==
4542 XML_SCHEMA_TYPE_SEQUENCE)))
4543 /* 1.1.2 */
4544 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4545 else if ((typeDecl->subtypes->type ==
4546 XML_SCHEMA_TYPE_CHOICE)
4547 && (typeDecl->subtypes->subtypes == NULL))
4548 /* 1.1.3 */
4549 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004550
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004551 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4552 typeDecl->baseNs);
4553 if (base == NULL) {
4554 xmlSchemaPErr(ctxt, typeDecl->node,
4555 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4556 "Schemas: base type %s of type %s not found\n",
4557 typeDecl->base, name);
4558 return;
4559 }
Daniel Veillard2582a332004-04-18 19:49:46 +00004560 if (typeDecl->recurse) {
4561 xmlSchemaPErr(ctxt, typeDecl->node,
4562 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4563 "Schemas: extension type %s is recursive\n",
4564 name, NULL);
4565 return;
4566 }
4567 typeDecl->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004568 xmlSchemaTypeFixup(base, ctxt, NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +00004569 typeDecl->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004570 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4571 /* 2.1 */
4572 typeDecl->contentType = base->contentType;
4573 } else if (base->contentType ==
4574 XML_SCHEMA_CONTENT_EMPTY) {
4575 /* 2.2 imbitable ! */
4576 typeDecl->contentType =
4577 XML_SCHEMA_CONTENT_ELEMENTS;
4578 } else {
4579 /* 2.3 imbitable pareil ! */
4580 typeDecl->contentType =
4581 XML_SCHEMA_CONTENT_ELEMENTS;
4582 }
4583 break;
4584 }
4585 case XML_SCHEMA_TYPE_COMPLEX:{
4586 if (typeDecl->subtypes == NULL) {
4587 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004588
4589 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4590 typeDecl->contentType =
4591 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004592 } else {
4593 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4594 typeDecl->contentType =
4595 XML_SCHEMA_CONTENT_MIXED;
4596 else {
4597 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4598 NULL);
4599 if (typeDecl->subtypes != NULL)
4600 typeDecl->contentType =
4601 typeDecl->subtypes->contentType;
4602 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004603 if (typeDecl->attributes == NULL)
4604 typeDecl->attributes =
4605 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004606 }
4607 break;
4608 }
4609 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4610 if (typeDecl->subtypes == NULL) {
4611 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004612 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4613 typeDecl->contentType =
4614 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004615 } else {
4616 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4617 typeDecl->contentType =
4618 XML_SCHEMA_CONTENT_MIXED;
4619 else {
4620 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4621 NULL);
4622 if (typeDecl->subtypes != NULL)
4623 typeDecl->contentType =
4624 typeDecl->subtypes->contentType;
4625 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004626 if (typeDecl->attributes == NULL)
4627 typeDecl->attributes =
4628 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 }
4630 break;
4631 }
4632 case XML_SCHEMA_TYPE_SEQUENCE:
4633 case XML_SCHEMA_TYPE_GROUP:
4634 case XML_SCHEMA_TYPE_ALL:
4635 case XML_SCHEMA_TYPE_CHOICE:
4636 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4637 break;
4638 case XML_SCHEMA_TYPE_BASIC:
4639 case XML_SCHEMA_TYPE_ANY:
4640 case XML_SCHEMA_TYPE_FACET:
4641 case XML_SCHEMA_TYPE_SIMPLE:
4642 case XML_SCHEMA_TYPE_UR:
4643 case XML_SCHEMA_TYPE_ELEMENT:
4644 case XML_SCHEMA_TYPE_ATTRIBUTE:
4645 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4646 case XML_SCHEMA_TYPE_NOTATION:
4647 case XML_SCHEMA_TYPE_LIST:
4648 case XML_SCHEMA_TYPE_UNION:
Daniel Veillard377e1a92004-04-16 16:30:05 +00004649 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004650 case XML_SCHEMA_FACET_MININCLUSIVE:
4651 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4652 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4653 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4654 case XML_SCHEMA_FACET_TOTALDIGITS:
4655 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4656 case XML_SCHEMA_FACET_PATTERN:
4657 case XML_SCHEMA_FACET_ENUMERATION:
4658 case XML_SCHEMA_FACET_WHITESPACE:
4659 case XML_SCHEMA_FACET_LENGTH:
4660 case XML_SCHEMA_FACET_MAXLENGTH:
4661 case XML_SCHEMA_FACET_MINLENGTH:
4662 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004663 if (typeDecl->subtypes != NULL)
4664 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004665 break;
4666 }
4667 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004668#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004669 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004670 xmlGenericError(xmlGenericErrorContext,
4671 "Type of %s : %s:%d :", name,
4672 typeDecl->node->doc->URL,
4673 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004674 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004675 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004676 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004677 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004678 case XML_SCHEMA_CONTENT_SIMPLE:
4679 xmlGenericError(xmlGenericErrorContext, "simple\n");
4680 break;
4681 case XML_SCHEMA_CONTENT_ELEMENTS:
4682 xmlGenericError(xmlGenericErrorContext, "elements\n");
4683 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004684 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004685 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4686 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004687 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004688 xmlGenericError(xmlGenericErrorContext, "empty\n");
4689 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004690 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004691 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4692 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004693 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004694 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4695 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004696 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004697 xmlGenericError(xmlGenericErrorContext, "basic\n");
4698 break;
4699 default:
4700 xmlGenericError(xmlGenericErrorContext,
4701 "not registered !!!\n");
4702 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004703 }
4704#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004705}
4706
4707/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004708 * xmlSchemaCheckFacet:
4709 * @facet: the facet
4710 * @typeDecl: the schema type definition
4711 * @ctxt: the schema parser context or NULL
4712 * @name: name of the type
4713 *
4714 * Checks the default values types, especially for facets
4715 *
4716 * Returns 0 if okay or -1 in cae of error
4717 */
4718int
4719xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004720 xmlSchemaTypePtr typeDecl,
4721 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004722{
4723 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4724 int ret = 0;
4725
4726 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004727 nonNegativeIntegerType =
4728 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4729 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004730 }
4731 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004732 case XML_SCHEMA_FACET_MININCLUSIVE:
4733 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4734 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4735 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4736 /*
4737 * Okay we need to validate the value
4738 * at that point.
4739 */
4740 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004741
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004742 vctxt = xmlSchemaNewValidCtxt(NULL);
4743 if (vctxt == NULL)
4744 break;
4745 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4746 facet->value);
4747 facet->val = vctxt->value;
4748 vctxt->value = NULL;
4749 if (facet->val == NULL) {
4750 /* error code */
4751 if (ctxt != NULL) {
4752 xmlSchemaPErr(ctxt, facet->node,
4753 XML_SCHEMAP_INVALID_FACET,
4754 "Schemas: type %s facet value %s invalid\n",
4755 name, facet->value);
4756 }
4757 ret = -1;
4758 }
4759 xmlSchemaFreeValidCtxt(vctxt);
4760 break;
4761 }
4762 case XML_SCHEMA_FACET_ENUMERATION:{
4763 /*
4764 * Okay we need to validate the value
4765 * at that point.
4766 */
4767 xmlSchemaValidCtxtPtr vctxt;
4768 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004769
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004770 vctxt = xmlSchemaNewValidCtxt(NULL);
4771 if (vctxt == NULL)
4772 break;
4773 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4774 facet->value);
4775 if (tmp != 0) {
4776 if (ctxt != NULL) {
4777 xmlSchemaPErr(ctxt, facet->node,
4778 XML_SCHEMAP_INVALID_ENUM,
4779 "Schemas: type %s enumeration value %s invalid\n",
4780 name, facet->value);
4781 }
4782 ret = -1;
4783 }
4784 xmlSchemaFreeValidCtxt(vctxt);
4785 break;
4786 }
4787 case XML_SCHEMA_FACET_PATTERN:
4788 facet->regexp = xmlRegexpCompile(facet->value);
4789 if (facet->regexp == NULL) {
4790 xmlSchemaPErr(ctxt, typeDecl->node,
4791 XML_SCHEMAP_REGEXP_INVALID,
4792 "Schemas: type %s facet regexp %s invalid\n",
4793 name, facet->value);
4794 ret = -1;
4795 }
4796 break;
4797 case XML_SCHEMA_FACET_TOTALDIGITS:
4798 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4799 case XML_SCHEMA_FACET_LENGTH:
4800 case XML_SCHEMA_FACET_MAXLENGTH:
4801 case XML_SCHEMA_FACET_MINLENGTH:{
4802 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004803
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004804 tmp =
4805 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4806 facet->value,
4807 &facet->val);
4808 if (tmp != 0) {
4809 /* error code */
4810 if (ctxt != NULL) {
4811 xmlSchemaPErr(ctxt, facet->node,
4812 XML_SCHEMAP_INVALID_FACET_VALUE,
4813 "Schemas: type %s facet value %s invalid\n",
4814 name, facet->value);
4815 }
4816 ret = -1;
4817 }
4818 break;
4819 }
4820 case XML_SCHEMA_FACET_WHITESPACE:{
4821 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4822 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4823 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4824 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4825 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4826 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4827 } else {
4828 if (ctxt != NULL) {
4829 xmlSchemaPErr(ctxt, facet->node,
4830 XML_SCHEMAP_INVALID_WHITE_SPACE,
4831 "Schemas: type %s whiteSpace value %s invalid\n",
4832 name, facet->value);
4833 }
4834 ret = -1;
4835 }
4836 }
4837 default:
4838 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004839 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004840 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004841}
4842
4843/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004844 * xmlSchemaCheckDefaults:
4845 * @typeDecl: the schema type definition
4846 * @ctxt: the schema parser context
4847 *
4848 * Checks the default values types, especially for facets
4849 */
4850static void
4851xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004852 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004853{
Daniel Veillard4255d502002-04-16 15:50:10 +00004854 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004855 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004856 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004857 if (typeDecl->facets != NULL) {
4858 xmlSchemaFacetPtr facet = typeDecl->facets;
4859
4860 while (facet != NULL) {
4861 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4862 facet = facet->next;
4863 }
4864 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004865 }
4866}
4867
4868/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004869 * xmlSchemaAttrGrpFixup:
4870 * @attrgrpDecl: the schema attribute definition
4871 * @ctxt: the schema parser context
4872 * @name: the attribute name
4873 *
4874 * Fixes finish doing the computations on the attributes definitions
4875 */
4876static void
4877xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004878 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004879{
4880 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004881 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004882 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004883 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004884 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004885 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004886
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004887 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4888 attrgrpDecl->refNs);
4889 if (ref == NULL) {
4890 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4891 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4892 "Schemas: attribute group %s reference %s not found\n",
4893 name, attrgrpDecl->ref);
4894 return;
4895 }
4896 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4897 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004898 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004899 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4900 "Schemas: attribute %s has no attributes nor reference\n",
4901 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004902 }
4903}
4904
4905/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004906 * xmlSchemaAttrFixup:
4907 * @attrDecl: the schema attribute definition
4908 * @ctxt: the schema parser context
4909 * @name: the attribute name
4910 *
4911 * Fixes finish doing the computations on the attributes definitions
4912 */
4913static void
4914xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004916{
4917 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004918 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004919 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004920 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004921 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004923
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004924 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4925 attrDecl->typeNs);
4926 if (type == NULL) {
4927 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4928 "Schemas: attribute %s type %s not found\n",
4929 name, attrDecl->typeName);
4930 }
4931 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004932 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004933 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004934
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004935 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4936 attrDecl->refNs);
4937 if (ref == NULL) {
4938 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4939 "Schemas: attribute %s reference %s not found\n",
4940 name, attrDecl->ref);
4941 return;
4942 }
4943 xmlSchemaAttrFixup(ref, ctxt, NULL);
4944 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004945 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004946 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4947 "Schemas: attribute %s has no type nor reference\n",
4948 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004949 }
4950}
4951
4952/**
4953 * xmlSchemaParse:
4954 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004955 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004956 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004957 * XML Shema struture which can be used to validate instances.
4958 * *WARNING* this interface is highly subject to change
4959 *
4960 * Returns the internal XML Schema structure built from the resource or
4961 * NULL in case of error
4962 */
4963xmlSchemaPtr
4964xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4965{
4966 xmlSchemaPtr ret = NULL;
4967 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004968 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004969 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004970 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004971
4972 xmlSchemaInitTypes();
4973
Daniel Veillard6045c902002-10-09 21:13:59 +00004974 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004975 return (NULL);
4976
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004977 nberrors = ctxt->nberrors;
4978 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004979 ctxt->counter = 0;
4980 ctxt->container = NULL;
4981
4982 /*
4983 * First step is to parse the input document into an DOM/Infoset
4984 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004985 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004986 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4987 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004988 if (doc == NULL) {
4989 xmlSchemaPErr(ctxt, NULL,
4990 XML_SCHEMAP_FAILED_LOAD,
4991 "xmlSchemaParse: could not load %s\n",
4992 ctxt->URL, NULL);
4993 return (NULL);
4994 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004995 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004996 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4997 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004998 if (doc == NULL) {
4999 xmlSchemaPErr(ctxt, NULL,
5000 XML_SCHEMAP_FAILED_PARSE,
5001 "xmlSchemaParse: could not parse\n",
5002 NULL, NULL);
5003 return (NULL);
5004 }
5005 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00005006 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00005007 } else if (ctxt->doc != NULL) {
5008 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005009 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00005010 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005011 xmlSchemaPErr(ctxt, NULL,
5012 XML_SCHEMAP_NOTHING_TO_PARSE,
5013 "xmlSchemaParse: could not parse\n",
5014 NULL, NULL);
5015 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005016 }
5017
5018 /*
5019 * Then extract the root and Schema parse it
5020 */
5021 root = xmlDocGetRootElement(doc);
5022 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005023 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
5024 XML_SCHEMAP_NOROOT,
5025 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00005026 if (!preserve) {
5027 xmlFreeDoc(doc);
5028 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005029 return (NULL);
5030 }
5031
5032 /*
5033 * Remove all the blank text nodes
5034 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005035 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00005036
5037 /*
5038 * Then do the parsing for good
5039 */
5040 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00005041 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00005042 if (!preserve) {
5043 xmlFreeDoc(doc);
5044 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005045 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00005046 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005047 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005048 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00005049
5050 /*
5051 * Then fix all the references.
5052 */
5053 ctxt->schema = ret;
5054 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005055 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005056
5057 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005058 * Then fixup all attributes declarations
5059 */
5060 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
5061
5062 /*
5063 * Then fixup all attributes group declarations
5064 */
5065 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
5066 ctxt);
5067
5068 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00005069 * Then fixup all types properties
5070 */
5071 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
5072
5073 /*
5074 * Then build the content model for all elements
5075 */
5076 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005077 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005078
5079 /*
5080 * Then check the defaults part of the type like facets values
5081 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
5083 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005084
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005085 if (ctxt->nberrors != 0) {
5086 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005087 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005088 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 return (ret);
5090}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005091
Daniel Veillard4255d502002-04-16 15:50:10 +00005092/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00005093 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005094 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005095 * @err: the error callback
5096 * @warn: the warning callback
5097 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005098 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005099 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005100 */
5101void
5102xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005103 xmlSchemaValidityErrorFunc err,
5104 xmlSchemaValidityWarningFunc warn, void *ctx)
5105{
Daniel Veillard4255d502002-04-16 15:50:10 +00005106 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005107 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005108 ctxt->error = err;
5109 ctxt->warning = warn;
5110 ctxt->userData = ctx;
5111}
5112
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005113/**
5114 * xmlSchemaFacetTypeToString:
5115 * @type: the facet type
5116 *
5117 * Convert the xmlSchemaTypeType to a char string.
5118 *
5119 * Returns the char string representation of the facet type if the
5120 * type is a facet and an "Internal Error" string otherwise.
5121 */
5122static const char *
5123xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5124{
5125 switch (type) {
5126 case XML_SCHEMA_FACET_PATTERN:
5127 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005128 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005129 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005130 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005131 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005132 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005133 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005134 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005135 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005136 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005137 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005138 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005139 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005140 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005141 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005142 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005143 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005144 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005145 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005146 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005147 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005148 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005149 return ("fractionDigits");
5150 default:
5151 break;
5152 }
5153 return ("Internal Error");
5154}
5155
5156/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005157 * xmlSchemaValidateFacetsInternal:
5158 * @ctxt: a schema validation context
5159 * @base: the base type
5160 * @facets: the list of facets to check
5161 * @value: the lexical repr of the value to validate
5162 * @val: the precomputed value
5163 * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
5164 *
5165 * Check a value against all facet conditions
5166 *
5167 * Returns 0 if the element is schemas valid, a positive error code
5168 * number otherwise and -1 in case of internal or API error.
5169 */
5170static int
5171xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
5172 xmlSchemaTypePtr base,
5173 xmlSchemaFacetPtr facets, const xmlChar * value, int fireErrors)
5174{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005175 int ret = 0;
5176 int tmp = 0;
5177 xmlSchemaTypeType type;
5178 xmlSchemaFacetPtr facet = facets;
5179
5180 while (facet != NULL) {
5181 type = facet->type;
5182 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005183 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005184
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005185 while (facet != NULL) {
5186 tmp =
5187 xmlSchemaValidateFacet(base, facet, value,
5188 ctxt->value);
5189 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005190 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 }
5192 facet = facet->next;
5193 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005194 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005195 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005196
5197 if (tmp != 0) {
5198 ret = tmp;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005199 if (fireErrors)
5200 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 +00005201 }
5202 if (facet != NULL)
5203 facet = facet->next;
5204 }
5205 return (ret);
5206}
5207
William M. Brack87640d52004-04-17 14:58:15 +00005208/**
5209 * xmlSchemaValidateFacets:
5210 * @ctxt: a schema validation context
5211 * @base: the base type
5212 * @facets: the list of facets to check
5213 * @value: the lexical repr of the value to validate
5214 * @val: the precomputed value
5215 *
5216 * Check a value against all facet conditions
5217 *
5218 * Returns 0 if the element is schemas valid, a positive error code
5219 * number otherwise and -1 in case of internal or API error.
5220 */
5221static int
5222xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5223 xmlSchemaTypePtr base,
5224 xmlSchemaFacetPtr facets, const xmlChar * value)
5225{
5226 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
5227}
5228
Daniel Veillard4255d502002-04-16 15:50:10 +00005229/************************************************************************
5230 * *
5231 * Simple type validation *
5232 * *
5233 ************************************************************************/
5234
5235/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00005236 * xmlSchemaValidateSimpleValueUnion:
5237 * @ctxt: a schema validation context
5238 * @type: the type declaration
5239 * @value: the value to validate
5240 *
5241 * Validates a value against a union.
5242 *
5243 * Returns 0 if the value is valid, a positive error code
5244 * number otherwise and -1 in case of internal or API error.
5245 */
5246static int
5247xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
5248 xmlSchemaTypePtr type, const xmlChar * value)
5249{
5250 int ret = 0;
5251 const xmlChar *cur, *end, *prefix, *ncName;
5252 xmlChar *tmp;
5253 xmlSchemaTypePtr subtype;
5254 xmlNsPtr ns;
5255 int len;
5256
5257
5258 /* Process referenced memberTypes. */
5259 cur = type->ref;
5260 do {
5261 while (IS_BLANK_CH(*cur))
5262 cur++;
5263 end = cur;
5264 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5265 end++;
5266 if (end == cur)
5267 break;
5268 tmp = xmlStrndup(cur, end - cur);
5269 ncName = xmlSplitQName3(tmp, &len);
5270 if (ncName != NULL) {
5271 prefix = xmlStrndup(tmp, len);
5272 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
5273 } else {
5274 prefix = NULL;
5275 ncName = tmp;
5276 }
5277 /* We won't do additional checks here, since they have been performed during parsing. */
5278 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5279 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
5280 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
5281 if (tmp != NULL)
5282 xmlFree(tmp);
5283 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00005284 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005285 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5286 if ((ret == 0) || (ret == -1)) {
5287 return (ret);
5288 }
5289 cur = end;
5290 } while (*cur != 0);
5291
5292 if (type->subtypes != NULL) {
5293 subtype = type->subtypes;
5294 do {
5295 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
5296 if ((ret == 0) || (ret == -1)) {
5297 return (ret);
5298 }
5299 subtype = subtype->next;
5300 } while (subtype != NULL);
5301 }
5302 return (ret);
5303}
5304
5305/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005306 * xmlSchemaValidateSimpleValue:
5307 * @ctxt: a schema validation context
5308 * @type: the type declaration
5309 * @value: the value to validate
5310 *
5311 * Validate a value against a simple type
5312 *
5313 * Returns 0 if the value is valid, a positive error code
5314 * number otherwise and -1 in case of internal or API error.
5315 */
5316static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005317xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005318 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005319{
Daniel Veillard377e1a92004-04-16 16:30:05 +00005320 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
5321}
5322
5323/**
5324 * xmlSchemaValidateSimpleValue:
5325 * @ctxt: a schema validation context
5326 * @type: the type declaration
5327 * @value: the value to validate
5328 * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
5329 *
5330 * Validate a value against a simple type
5331 *
5332 * Returns 0 if the value is valid, a positive error code
5333 * number otherwise and -1 in case of internal or API error.
5334 */
5335static int
5336xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
5337 xmlSchemaTypePtr type, const xmlChar * value, int fireErrors)
5338{
Daniel Veillard4255d502002-04-16 15:50:10 +00005339 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005340
Daniel Veillard4255d502002-04-16 15:50:10 +00005341 /*
5342 * First normalize the value accordingly to Schema Datatype
5343 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5344 */
5345 /*
5346 * Then check the normalized value against the lexical space of the
5347 * type.
5348 */
5349 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350 if (ctxt->value != NULL) {
5351 xmlSchemaFreeValue(ctxt->value);
5352 ctxt->value = NULL;
5353 }
5354 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5355 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005356 if ((fireErrors) && (ret != 0)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005357 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 +00005358 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 xmlSchemaTypePtr base;
5361 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005362
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005363 base = type->baseType;
5364 if (base != NULL) {
Daniel Veillard377e1a92004-04-16 16:30:05 +00005365 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005366 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005367 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005368 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005369
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005370 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005371 * Do not validate facets or attributes when working on
5372 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005373 */
5374 if (ctxt->schema != NULL) {
5375 if (ret == 0) {
5376 facet = type->facets;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005377 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005378 }
5379 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005380 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005381 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005382
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005383 base = type->subtypes;
5384 if (base != NULL) {
Daniel Veillard377e1a92004-04-16 16:30:05 +00005385 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005386 } else {
5387 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005388 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005390 const xmlChar *cur, *end;
5391 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005392 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005393
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005394 base = type->subtypes;
5395 if (base == NULL) {
5396 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5397 "Internal: List type %s has no base type\n",
5398 type->name, NULL);
5399 return (-1);
5400 }
5401 cur = value;
5402 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005403 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005404 cur++;
5405 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005406 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407 end++;
5408 if (end == cur)
5409 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005410 tmp = xmlStrndup(cur, end - cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005411 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base, tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005412 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005413 if (ret2 != 0)
5414 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005415 cur = end;
5416 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005417 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
5418 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
5419 if ((fireErrors) && (ret != 0)) {
5420 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate type %s\n", type->name, NULL);
5421 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005422 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005423 TODO
5424 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005425 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005426}
5427
5428/************************************************************************
5429 * *
5430 * DOM Validation code *
5431 * *
5432 ************************************************************************/
5433
5434static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005435 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005436static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005437 xmlNodePtr elem,
5438 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005439static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005440 xmlNodePtr elem,
5441 xmlSchemaElementPtr elemDecl,
5442 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005443
5444/**
5445 * xmlSchemaRegisterAttributes:
5446 * @ctxt: a schema validation context
5447 * @attrs: a list of attributes
5448 *
5449 * Register the list of attributes as the set to be validated on that element
5450 *
5451 * Returns -1 in case of error, 0 otherwise
5452 */
5453static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005454xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5455{
Daniel Veillard4255d502002-04-16 15:50:10 +00005456 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005457 if ((attrs->ns != NULL) &&
5458 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5459 attrs = attrs->next;
5460 continue;
5461 }
5462 if (ctxt->attrNr >= ctxt->attrMax) {
5463 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005464
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005465 ctxt->attrMax *= 2;
5466 tmp = (xmlSchemaAttrStatePtr)
5467 xmlRealloc(ctxt->attr, ctxt->attrMax *
5468 sizeof(xmlSchemaAttrState));
5469 if (tmp == NULL) {
5470 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5471 ctxt->attrMax /= 2;
5472 return (-1);
5473 }
5474 ctxt->attr = tmp;
5475 }
5476 ctxt->attr[ctxt->attrNr].attr = attrs;
5477 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5478 ctxt->attrNr++;
5479 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005480 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005481 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005482}
5483
5484/**
5485 * xmlSchemaCheckAttributes:
5486 * @ctxt: a schema validation context
5487 * @node: the node carrying it.
5488 *
5489 * Check that the registered set of attributes on the current node
5490 * has been properly validated.
5491 *
5492 * Returns 0 if validity constraints are met, 1 otherwise.
5493 */
5494static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005495xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5496{
Daniel Veillard4255d502002-04-16 15:50:10 +00005497 int ret = 0;
5498 int i;
5499
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005500 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5501 if (ctxt->attr[i].attr == NULL)
5502 break;
5503 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5504 ret = 1;
5505 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5506 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005507 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005508 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005509}
5510
5511/**
5512 * xmlSchemaValidateSimpleContent:
5513 * @ctxt: a schema validation context
5514 * @elem: an element
5515 * @type: the type declaration
5516 *
5517 * Validate the content of an element expected to be a simple type
5518 *
5519 * Returns 0 if the element is schemas valid, a positive error code
5520 * number otherwise and -1 in case of internal or API error.
5521 */
5522static int
5523xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005524 xmlNodePtr node ATTRIBUTE_UNUSED)
5525{
Daniel Veillard4255d502002-04-16 15:50:10 +00005526 xmlNodePtr child;
5527 xmlSchemaTypePtr type, base;
5528 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005529 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005530
5531 child = ctxt->node;
5532 type = ctxt->type;
5533
5534 /*
5535 * Validation Rule: Element Locally Valid (Type): 3.1.3
5536 */
5537 value = xmlNodeGetContent(child);
5538 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5539 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005540 case XML_SCHEMA_TYPE_RESTRICTION:{
5541 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005542
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005543 base = type->baseType;
5544 if (base != NULL) {
5545 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5546 } else {
5547 TODO}
5548 if (ret == 0) {
5549 facet = type->facets;
5550 ret =
5551 xmlSchemaValidateFacets(ctxt, base, facet, value);
5552 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005553 if ((ret == 0) && (type->attributes != NULL)) {
5554 ret = xmlSchemaValidateAttributes(ctxt, node,
5555 type->attributes);
5556 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005557 break;
5558 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005559 case XML_SCHEMA_TYPE_EXTENSION:{
5560 TODO
5561 break;
5562 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005563 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005564 TODO
5565 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005566 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005567 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005568
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005569 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005570}
5571
5572/**
5573 * xmlSchemaValidateCheckNodeList
5574 * @nodelist: the list of nodes
5575 *
5576 * Check the node list is only made of text nodes and entities pointing
5577 * to text nodes
5578 *
5579 * Returns 1 if true, 0 if false and -1 in case of error
5580 */
5581static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005582xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5583{
Daniel Veillard4255d502002-04-16 15:50:10 +00005584 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005585 if (nodelist->type == XML_ENTITY_REF_NODE) {
5586 TODO /* implement recursion in the entity content */
5587 }
5588 if ((nodelist->type != XML_TEXT_NODE) &&
5589 (nodelist->type != XML_COMMENT_NODE) &&
5590 (nodelist->type != XML_PI_NODE) &&
5591 (nodelist->type != XML_PI_NODE)) {
5592 return (0);
5593 }
5594 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005595 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005596 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005597}
5598
5599/**
5600 * xmlSchemaSkipIgnored:
5601 * @ctxt: a schema validation context
5602 * @type: the current type context
5603 * @node: the top node.
5604 *
5605 * Skip ignorable nodes in that context
5606 *
5607 * Returns the new sibling
5608 * number otherwise and -1 in case of internal or API error.
5609 */
5610static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005611xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005612 xmlSchemaTypePtr type, xmlNodePtr node)
5613{
Daniel Veillard4255d502002-04-16 15:50:10 +00005614 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005615
Daniel Veillard4255d502002-04-16 15:50:10 +00005616 /*
5617 * TODO complete and handle entities
5618 */
5619 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005620 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005621 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 ((node->type == XML_COMMENT_NODE) ||
5623 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5624 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5625 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5626 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005627 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005628 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005629}
5630
5631/**
5632 * xmlSchemaValidateCallback:
5633 * @ctxt: a schema validation context
5634 * @name: the name of the element detected (might be NULL)
5635 * @type: the type
5636 *
5637 * A transition has been made in the automata associated to an element
5638 * content model
5639 */
5640static void
5641xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 const xmlChar * name ATTRIBUTE_UNUSED,
5643 xmlSchemaTypePtr type, xmlNodePtr node)
5644{
Daniel Veillard4255d502002-04-16 15:50:10 +00005645 xmlSchemaTypePtr oldtype = ctxt->type;
5646 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005647
Daniel Veillard4255d502002-04-16 15:50:10 +00005648#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005649 xmlGenericError(xmlGenericErrorContext,
5650 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005651 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005652#endif
5653 ctxt->type = type;
5654 ctxt->node = node;
5655 xmlSchemaValidateContent(ctxt, node);
5656 ctxt->type = oldtype;
5657 ctxt->node = oldnode;
5658}
5659
5660
5661#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005662
Daniel Veillard4255d502002-04-16 15:50:10 +00005663/**
5664 * xmlSchemaValidateSimpleRestrictionType:
5665 * @ctxt: a schema validation context
5666 * @node: the top node.
5667 *
5668 * Validate the content of a restriction type.
5669 *
5670 * Returns 0 if the element is schemas valid, a positive error code
5671 * number otherwise and -1 in case of internal or API error.
5672 */
5673static int
5674xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5675 xmlNodePtr node)
5676{
5677 xmlNodePtr child;
5678 xmlSchemaTypePtr type;
5679 int ret;
5680
5681 child = ctxt->node;
5682 type = ctxt->type;
5683
5684 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005685 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005686 return (-1);
5687 }
5688 /*
5689 * Only text and text based entities references shall be found there
5690 */
5691 ret = xmlSchemaValidateCheckNodeList(child);
5692 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005693 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005694 return (-1);
5695 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005696 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 +00005697 return (-1);
5698 }
5699 ctxt->type = type->subtypes;
5700 xmlSchemaValidateContent(ctxt, node);
5701 ctxt->type = type;
5702 return (ret);
5703}
5704#endif
5705
5706/**
5707 * xmlSchemaValidateSimpleType:
5708 * @ctxt: a schema validation context
5709 * @node: the top node.
5710 *
5711 * Validate the content of an simple type.
5712 *
5713 * Returns 0 if the element is schemas valid, a positive error code
5714 * number otherwise and -1 in case of internal or API error.
5715 */
5716static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005717xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5718{
Daniel Veillard4255d502002-04-16 15:50:10 +00005719 xmlNodePtr child;
5720 xmlSchemaTypePtr type;
5721 xmlAttrPtr attr;
5722 int ret;
5723
5724 child = ctxt->node;
5725 type = ctxt->type;
5726
5727 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005728 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5729 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005730 }
5731 /*
5732 * Only text and text based entities references shall be found there
5733 */
5734 ret = xmlSchemaValidateCheckNodeList(child);
5735 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005736 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5737 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005738 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005739 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5740 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005741 }
5742 /*
5743 * Validation Rule: Element Locally Valid (Type): 3.1.1
5744 */
5745 attr = node->properties;
5746 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005747 if ((attr->ns == NULL) ||
5748 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5749 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5750 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5751 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5752 (!xmlStrEqual
5753 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5754 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5755 return (ctxt->err);
5756 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005757 }
5758
5759 ctxt->type = type->subtypes;
5760 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5761 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005762 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005763}
5764
5765/**
5766 * xmlSchemaValidateElementType:
5767 * @ctxt: a schema validation context
5768 * @node: the top node.
5769 *
5770 * Validate the content of an element type.
5771 * Validation Rule: Element Locally Valid (Complex Type)
5772 *
5773 * Returns 0 if the element is schemas valid, a positive error code
5774 * number otherwise and -1 in case of internal or API error.
5775 */
5776static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005777xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5778{
Daniel Veillard4255d502002-04-16 15:50:10 +00005779 xmlNodePtr child;
5780 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005781 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005782 xmlSchemaElementPtr decl;
5783 int ret, attrBase;
5784
5785 oldregexp = ctxt->regexp;
5786
5787 child = ctxt->node;
5788 type = ctxt->type;
5789
5790 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005791 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5792 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005793 }
5794 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005795 if (type->minOccurs > 0) {
5796 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5797 }
5798 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005799 }
5800
5801 /*
5802 * Verify the element matches
5803 */
5804 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005805 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5806 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005807 }
5808 /*
5809 * Verify the attributes
5810 */
5811 attrBase = ctxt->attrBase;
5812 ctxt->attrBase = ctxt->attrNr;
5813 xmlSchemaRegisterAttributes(ctxt, child->properties);
5814 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5815 /*
5816 * Verify the element content recursively
5817 */
5818 decl = (xmlSchemaElementPtr) type;
5819 oldregexp = ctxt->regexp;
5820 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005821 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5822 (xmlRegExecCallbacks)
5823 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005824#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005825 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005826#endif
5827 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5829 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005830
5831 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005832 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005833#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005834 xmlGenericError(xmlGenericErrorContext,
5835 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005836#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005837 if (ret == 0) {
5838 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5839 } else if (ret < 0) {
5840 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005841#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005842 } else {
5843 xmlGenericError(xmlGenericErrorContext,
5844 "Element %s content check succeeded\n",
5845 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005846
5847#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005848 }
5849 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 }
5851 /*
5852 * Verify that all attributes were Schemas-validated
5853 */
5854 xmlSchemaCheckAttributes(ctxt, node);
5855 ctxt->attrNr = ctxt->attrBase;
5856 ctxt->attrBase = attrBase;
5857
5858 ctxt->regexp = oldregexp;
5859
5860 ctxt->node = child;
5861 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005862 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005863}
5864
5865/**
5866 * xmlSchemaValidateBasicType:
5867 * @ctxt: a schema validation context
5868 * @node: the top node.
5869 *
5870 * Validate the content of an element expected to be a basic type type
5871 *
5872 * Returns 0 if the element is schemas valid, a positive error code
5873 * number otherwise and -1 in case of internal or API error.
5874 */
5875static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005876xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5877{
Daniel Veillard4255d502002-04-16 15:50:10 +00005878 int ret;
5879 xmlNodePtr child, cur;
5880 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005881 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005882
5883 child = ctxt->node;
5884 type = ctxt->type;
5885
5886 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005887 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5888 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005889 }
5890 /*
5891 * First check the content model of the node.
5892 */
5893 cur = child;
5894 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005895 switch (cur->type) {
5896 case XML_TEXT_NODE:
5897 case XML_CDATA_SECTION_NODE:
5898 case XML_PI_NODE:
5899 case XML_COMMENT_NODE:
5900 case XML_XINCLUDE_START:
5901 case XML_XINCLUDE_END:
5902 break;
5903 case XML_ENTITY_REF_NODE:
5904 case XML_ENTITY_NODE:
5905 TODO break;
5906 case XML_ELEMENT_NODE:
5907 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5908 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005909 case XML_ATTRIBUTE_NODE:
5910 case XML_DOCUMENT_NODE:
5911 case XML_DOCUMENT_TYPE_NODE:
5912 case XML_DOCUMENT_FRAG_NODE:
5913 case XML_NOTATION_NODE:
5914 case XML_HTML_DOCUMENT_NODE:
5915 case XML_DTD_NODE:
5916 case XML_ELEMENT_DECL:
5917 case XML_ATTRIBUTE_DECL:
5918 case XML_ENTITY_DECL:
5919 case XML_NAMESPACE_DECL:
5920#ifdef LIBXML_DOCB_ENABLED
5921 case XML_DOCB_DOCUMENT_NODE:
5922#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005923 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5924 return (ctxt->err);
5925 }
5926 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005927 }
5928 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005929 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005930 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005931 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005932
5933 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005934 xmlSchemaFreeValue(ctxt->value);
5935 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005936 }
5937 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5938 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005939 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005940 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005941 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 +00005942 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005943 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005944}
5945
5946/**
5947 * xmlSchemaValidateComplexType:
5948 * @ctxt: a schema validation context
5949 * @node: the top node.
5950 *
5951 * Validate the content of an element expected to be a complex type type
5952 * xmlschema-1.html#cvc-complex-type
5953 * Validation Rule: Element Locally Valid (Complex Type)
5954 *
5955 * Returns 0 if the element is schemas valid, a positive error code
5956 * number otherwise and -1 in case of internal or API error.
5957 */
5958static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005959xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5960{
Daniel Veillard4255d502002-04-16 15:50:10 +00005961 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005962 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005963 int ret;
5964
5965 child = ctxt->node;
5966 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005967 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005968
Daniel Veillard4255d502002-04-16 15:50:10 +00005969 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005970 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005971 if (type->baseType != NULL) {
5972 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005973 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5974 }
5975 if (type->attributes != NULL) {
5976 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5977 }
5978 subtype = type->subtypes;
5979 while (subtype != NULL) {
5980 ctxt->type = subtype;
5981 xmlSchemaValidateComplexType(ctxt, node);
5982 subtype = subtype->next;
5983 }
5984 break;
5985 case XML_SCHEMA_CONTENT_ELEMENTS:
5986 case XML_SCHEMA_CONTENT_MIXED:
5987 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5988 /*
5989 * Skip ignorable nodes in that context
5990 */
5991 child = xmlSchemaSkipIgnored(ctxt, type, child);
5992 while (child != NULL) {
5993 if (child->type == XML_ELEMENT_NODE) {
5994 ret = xmlRegExecPushString(ctxt->regexp,
5995 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005996#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005997 if (ret < 0)
5998 xmlGenericError(xmlGenericErrorContext,
5999 " --> %s Error\n", child->name);
6000 else
6001 xmlGenericError(xmlGenericErrorContext,
6002 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006003#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006004 }
6005 child = child->next;
6006 /*
6007 * Skip ignorable nodes in that context
6008 */
6009 child = xmlSchemaSkipIgnored(ctxt, type, child);
6010 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00006011 if (type->attributes != NULL) {
6012 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6013 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006014 break;
6015 case XML_SCHEMA_CONTENT_BASIC:{
6016 if (type->subtypes != NULL) {
6017 ctxt->type = type->subtypes;
6018 xmlSchemaValidateComplexType(ctxt, node);
6019 }
6020 if (type->baseType != NULL) {
6021 ctxt->type = type->baseType;
6022 xmlSchemaValidateBasicType(ctxt, node);
6023 }
6024 if (type->attributes != NULL) {
6025 xmlSchemaValidateAttributes(ctxt, node,
6026 type->attributes);
6027 }
6028 ctxt->type = type;
6029 break;
6030 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006031 case XML_SCHEMA_CONTENT_SIMPLE:{
6032 if (type->subtypes != NULL) {
6033 ctxt->type = type->subtypes;
6034 xmlSchemaValidateComplexType(ctxt, node);
6035 }
6036 if (type->baseType != NULL) {
6037 ctxt->type = type->baseType;
6038 xmlSchemaValidateComplexType(ctxt, node);
6039 }
6040 if (type->attributes != NULL) {
6041 xmlSchemaValidateAttributes(ctxt, node,
6042 type->attributes);
6043 }
6044 ctxt->type = type;
6045 break;
6046 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006047 default:
6048 TODO xmlGenericError(xmlGenericErrorContext,
6049 "unimplemented content type %d\n",
6050 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006052 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006053}
6054
6055/**
6056 * xmlSchemaValidateContent:
6057 * @ctxt: a schema validation context
6058 * @elem: an element
6059 * @type: the type declaration
6060 *
6061 * Validate the content of an element against the type.
6062 *
6063 * Returns 0 if the element is schemas valid, a positive error code
6064 * number otherwise and -1 in case of internal or API error.
6065 */
6066static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006067xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
6068{
Daniel Veillard4255d502002-04-16 15:50:10 +00006069 xmlNodePtr child;
6070 xmlSchemaTypePtr type;
6071
6072 child = ctxt->node;
6073 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006074 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00006075
Daniel Veillarde19fc232002-04-22 16:01:24 +00006076 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00006077 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00006078
Daniel Veillard4255d502002-04-16 15:50:10 +00006079 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006080 case XML_SCHEMA_TYPE_ANY:
6081 /* Any type will do it, fine */
6082 TODO /* handle recursivity */
6083 break;
6084 case XML_SCHEMA_TYPE_COMPLEX:
6085 xmlSchemaValidateComplexType(ctxt, node);
6086 break;
6087 case XML_SCHEMA_TYPE_ELEMENT:{
6088 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
6089
6090 /*
6091 * Handle element reference here
6092 */
6093 if (decl->ref != NULL) {
6094 if (decl->refDecl == NULL) {
6095 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
6096 return (-1);
6097 }
6098 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
6099 decl = decl->refDecl;
6100 }
6101 xmlSchemaValidateElementType(ctxt, node);
6102 ctxt->type = type;
6103 break;
6104 }
6105 case XML_SCHEMA_TYPE_BASIC:
6106 xmlSchemaValidateBasicType(ctxt, node);
6107 break;
6108 case XML_SCHEMA_TYPE_FACET:
6109 TODO break;
6110 case XML_SCHEMA_TYPE_SIMPLE:
6111 xmlSchemaValidateSimpleType(ctxt, node);
6112 break;
6113 case XML_SCHEMA_TYPE_SEQUENCE:
6114 TODO break;
6115 case XML_SCHEMA_TYPE_CHOICE:
6116 TODO break;
6117 case XML_SCHEMA_TYPE_ALL:
6118 TODO break;
6119 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
6120 TODO break;
6121 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
6122 TODO break;
6123 case XML_SCHEMA_TYPE_UR:
6124 TODO break;
6125 case XML_SCHEMA_TYPE_RESTRICTION:
6126 /*xmlSchemaValidateRestrictionType(ctxt, node); */
6127 TODO break;
6128 case XML_SCHEMA_TYPE_EXTENSION:
6129 TODO break;
6130 case XML_SCHEMA_TYPE_ATTRIBUTE:
6131 TODO break;
6132 case XML_SCHEMA_TYPE_GROUP:
6133 TODO break;
6134 case XML_SCHEMA_TYPE_NOTATION:
6135 TODO break;
6136 case XML_SCHEMA_TYPE_LIST:
6137 TODO break;
6138 case XML_SCHEMA_TYPE_UNION:
6139 TODO break;
6140 case XML_SCHEMA_FACET_MININCLUSIVE:
6141 TODO break;
6142 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6143 TODO break;
6144 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6145 TODO break;
6146 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6147 TODO break;
6148 case XML_SCHEMA_FACET_TOTALDIGITS:
6149 TODO break;
6150 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6151 TODO break;
6152 case XML_SCHEMA_FACET_PATTERN:
6153 TODO break;
6154 case XML_SCHEMA_FACET_ENUMERATION:
6155 TODO break;
6156 case XML_SCHEMA_FACET_WHITESPACE:
6157 TODO break;
6158 case XML_SCHEMA_FACET_LENGTH:
6159 TODO break;
6160 case XML_SCHEMA_FACET_MAXLENGTH:
6161 TODO break;
6162 case XML_SCHEMA_FACET_MINLENGTH:
6163 TODO break;
6164 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
6165 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00006166 }
6167 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
6168
6169 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006170 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 ctxt->node = ctxt->node->next;
6172 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006174}
6175
6176/**
6177 * xmlSchemaValidateType:
6178 * @ctxt: a schema validation context
6179 * @elem: an element
6180 * @type: the list of type declarations
6181 *
6182 * Validate the content of an element against the types.
6183 *
6184 * Returns 0 if the element is schemas valid, a positive error code
6185 * number otherwise and -1 in case of internal or API error.
6186 */
6187static int
6188xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
6190{
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 xmlChar *nil;
6192
Daniel Veillard2db8c122003-07-08 12:16:59 +00006193 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006194 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00006195
Daniel Veillard4255d502002-04-16 15:50:10 +00006196 /*
6197 * 3.3.4 : 2
6198 */
6199 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006200 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
6201 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 }
6203 /*
6204 * 3.3.4: 3
6205 */
6206 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6207 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006208 /* 3.3.4: 3.2 */
6209 if (xmlStrEqual(nil, BAD_CAST "true")) {
6210 if (elem->children != NULL) {
6211 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
6212 return (ctxt->err);
6213 }
6214 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6215 (elemDecl->value != NULL)) {
6216 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
6217 return (ctxt->err);
6218 }
6219 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006220 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006221 /* 3.3.4: 3.1 */
6222 if (nil != NULL) {
6223 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
6224 xmlFree(nil);
6225 return (ctxt->err);
6226 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006227 }
6228
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006229 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006230
6231 ctxt->type = elemDecl->subtypes;
6232 ctxt->node = elem->children;
6233 xmlSchemaValidateContent(ctxt, elem);
6234 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006235
6236 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006237}
6238
6239
6240/**
6241 * xmlSchemaValidateAttributes:
6242 * @ctxt: a schema validation context
6243 * @elem: an element
6244 * @attributes: the list of attribute declarations
6245 *
6246 * Validate the attributes of an element.
6247 *
6248 * Returns 0 if the element is schemas valid, a positive error code
6249 * number otherwise and -1 in case of internal or API error.
6250 */
6251static int
6252xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006253 xmlSchemaAttributePtr attributes)
6254{
William M. Brack87640d52004-04-17 14:58:15 +00006255 int i, ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006256 xmlAttrPtr attr;
6257 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006258 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006259 int found;
Daniel Veillard4255d502002-04-16 15:50:10 +00006260
6261 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006262 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006263 while (attributes != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006264 found = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006265 /*
6266 * Handle attribute groups
6267 */
6268 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6269 group = (xmlSchemaAttributeGroupPtr) attributes;
6270 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6271 attributes = group->next;
6272 continue;
6273 }
6274 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6275 attr = ctxt->attr[i].attr;
6276 if (attr == NULL)
6277 continue;
6278 if (attributes->ref != NULL) {
6279 if (!xmlStrEqual(attr->name, attributes->ref))
6280 continue;
6281 if (attr->ns != NULL) {
6282 if ((attributes->refNs == NULL) ||
6283 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6284 continue;
6285 } else if (attributes->refNs != NULL) {
6286 continue;
6287 }
6288 } else {
6289 if (!xmlStrEqual(attr->name, attributes->name))
6290 continue;
6291 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006292 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006293 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006294 if (attr->ns == NULL) {
6295 /*
6296 * accept an unqualified attribute only if the declaration
6297 * is unqualified or if the schemas allowed it.
6298 */
6299 if ((attributes->targetNamespace != NULL) &&
6300 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6301 continue;
6302 } else {
6303 if (attributes->targetNamespace == NULL)
6304 continue;
6305 if (!xmlStrEqual(attributes->targetNamespace,
6306 attr->ns->href))
6307 continue;
6308 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006309 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006310 found = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006311 ctxt->cur = (xmlNodePtr) attributes;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006312
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006313 if (attributes->subtypes == NULL) {
6314 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6315 continue;
6316 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006317
6318 if (attributes->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6319 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INVALIDATTR, "attribute %s on %s is prohibited\n", attributes->name, elem->name);
6320 /* Setting the state to XML_SCHEMAS_ATTR_CHECKED seems not very logical but it
6321 surpresses the "attribute is unknown" error report. Please change this if you know better */
6322 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6323 break;
6324 }
6325
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006326 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6327 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6328 value);
6329 if (ret != 0) {
6330 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6331 } else {
6332 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6333 }
6334 if (value != NULL) {
6335 xmlFree(value);
6336 }
6337 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00006338 if ((!found) && (attributes->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6339 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_MISSING, "required attribute %s on %s is missing\n", attributes->name, elem->name);
6340 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006341 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006342 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006343 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006344}
6345
6346/**
6347 * xmlSchemaValidateElement:
6348 * @ctxt: a schema validation context
6349 * @elem: an element
6350 *
6351 * Validate an element in a tree
6352 *
6353 * Returns 0 if the element is schemas valid, a positive error code
6354 * number otherwise and -1 in case of internal or API error.
6355 */
6356static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006357xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6358{
Daniel Veillard4255d502002-04-16 15:50:10 +00006359 xmlSchemaElementPtr elemDecl;
6360 int ret, attrBase;
6361
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006362 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006363 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6364 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006365 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006366 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6367 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006368 }
6369 /*
6370 * special case whe elementFormDefault is unqualified for top-level elem.
6371 */
6372 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6373 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6374 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6375 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6376 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6377 elem->name, NULL, NULL);
6378 }
6379
Daniel Veillard4255d502002-04-16 15:50:10 +00006380 /*
6381 * 3.3.4 : 1
6382 */
6383 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006384 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6385 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006386 }
6387 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006388 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6389 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006390 }
6391 /*
6392 * Verify the attributes
6393 */
6394 attrBase = ctxt->attrBase;
6395 ctxt->attrBase = ctxt->attrNr;
6396 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6397 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6398 /*
6399 * Verify the element content recursively
6400 */
6401 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006402 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6403 (xmlRegExecCallbacks)
6404 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006405#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006406 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006407#endif
6408 }
6409 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006410 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006411 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006412#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006413 xmlGenericError(xmlGenericErrorContext,
6414 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006415#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006416 if (ret == 0) {
6417 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6418 } else if (ret < 0) {
6419 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006420#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006421 } else {
6422 xmlGenericError(xmlGenericErrorContext,
6423 "Element %s content check succeeded\n",
6424 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006425
6426#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006427 }
6428 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006429 }
6430 /*
6431 * Verify that all attributes were Schemas-validated
6432 */
6433 xmlSchemaCheckAttributes(ctxt, elem);
6434 ctxt->attrNr = ctxt->attrBase;
6435 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006436
6437 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006438}
6439
6440/**
6441 * xmlSchemaValidateDocument:
6442 * @ctxt: a schema validation context
6443 * @doc: a parsed document tree
6444 *
6445 * Validate a document tree in memory.
6446 *
6447 * Returns 0 if the document is schemas valid, a positive error code
6448 * number otherwise and -1 in case of internal or API error.
6449 */
6450static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006451xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6452{
Daniel Veillard4255d502002-04-16 15:50:10 +00006453 xmlNodePtr root;
6454 xmlSchemaElementPtr elemDecl;
6455
6456 root = xmlDocGetRootElement(doc);
6457 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006458 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6459 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006460 }
6461 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006462 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6463 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006464 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006465 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6466 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006467 /*
6468 * special case whe elementFormDefault is unqualified for top-level elem.
6469 */
6470 if ((elemDecl == NULL) && (root->ns != NULL) &&
6471 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6472 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6473 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6474 root->name, NULL, NULL);
6475 }
6476
Daniel Veillard4255d502002-04-16 15:50:10 +00006477 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006478 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006479 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006480 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006481 }
6482 /*
6483 * Okay, start the recursive validation
6484 */
6485 xmlSchemaValidateElement(ctxt, root);
6486
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006487 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006488}
6489
6490/************************************************************************
6491 * *
6492 * SAX Validation code *
6493 * *
6494 ************************************************************************/
6495
6496/************************************************************************
6497 * *
6498 * Validation interfaces *
6499 * *
6500 ************************************************************************/
6501
6502/**
6503 * xmlSchemaNewValidCtxt:
6504 * @schema: a precompiled XML Schemas
6505 *
6506 * Create an XML Schemas validation context based on the given schema
6507 *
6508 * Returns the validation context or NULL in case of error
6509 */
6510xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006511xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6512{
Daniel Veillard4255d502002-04-16 15:50:10 +00006513 xmlSchemaValidCtxtPtr ret;
6514
6515 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6516 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006517 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006518 return (NULL);
6519 }
6520 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6521 ret->schema = schema;
6522 ret->attrNr = 0;
6523 ret->attrMax = 10;
6524 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006525 sizeof
6526 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006527 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006528 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6529 free(ret);
6530 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006531 }
6532 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6533 return (ret);
6534}
6535
6536/**
6537 * xmlSchemaFreeValidCtxt:
6538 * @ctxt: the schema validation context
6539 *
6540 * Free the resources associated to the schema validation context
6541 */
6542void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006543xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6544{
Daniel Veillard4255d502002-04-16 15:50:10 +00006545 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006546 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006547 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006548 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006549 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006550 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006551 xmlFree(ctxt);
6552}
6553
6554/**
6555 * xmlSchemaSetValidErrors:
6556 * @ctxt: a schema validation context
6557 * @err: the error function
6558 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006559 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006560 *
6561 * Set the error and warning callback informations
6562 */
6563void
6564xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006565 xmlSchemaValidityErrorFunc err,
6566 xmlSchemaValidityWarningFunc warn, void *ctx)
6567{
Daniel Veillard4255d502002-04-16 15:50:10 +00006568 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006569 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006570 ctxt->error = err;
6571 ctxt->warning = warn;
6572 ctxt->userData = ctx;
6573}
6574
6575/**
6576 * xmlSchemaValidateDoc:
6577 * @ctxt: a schema validation context
6578 * @doc: a parsed document tree
6579 *
6580 * Validate a document tree in memory.
6581 *
6582 * Returns 0 if the document is schemas valid, a positive error code
6583 * number otherwise and -1 in case of internal or API error.
6584 */
6585int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006586xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6587{
Daniel Veillard4255d502002-04-16 15:50:10 +00006588 int ret;
6589
6590 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006591 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006592
6593 ctxt->doc = doc;
6594 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006595 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006596}
6597
6598/**
6599 * xmlSchemaValidateStream:
6600 * @ctxt: a schema validation context
6601 * @input: the input to use for reading the data
6602 * @enc: an optional encoding information
6603 * @sax: a SAX handler for the resulting events
6604 * @user_data: the context to provide to the SAX handler.
6605 *
6606 * Validate a document tree in memory.
6607 *
6608 * Returns 0 if the document is schemas valid, a positive error code
6609 * number otherwise and -1 in case of internal or API error.
6610 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611int
Daniel Veillard4255d502002-04-16 15:50:10 +00006612xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006613 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6614 xmlSAXHandlerPtr sax, void *user_data)
6615{
Daniel Veillard4255d502002-04-16 15:50:10 +00006616 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006617 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006618 ctxt->input = input;
6619 ctxt->enc = enc;
6620 ctxt->sax = sax;
6621 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006622 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006623}
6624
6625#endif /* LIBXML_SCHEMAS_ENABLED */