blob: 2266f497abaf9a3002684ae306d1ef958865ab9c [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);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000186/************************************************************************
187 * *
188 * Datatype error handlers *
189 * *
190 ************************************************************************/
191
192/**
193 * xmlSchemaPErrMemory:
194 * @node: a context node
195 * @extra: extra informations
196 *
197 * Handle an out of memory condition
198 */
199static void
200xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
201 const char *extra, xmlNodePtr node)
202{
203 if (ctxt != NULL)
204 ctxt->nberrors++;
205 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
206 extra);
207}
208
209/**
210 * xmlSchemaPErr:
211 * @ctxt: the parsing context
212 * @node: the context node
213 * @error: the error code
214 * @msg: the error message
215 * @str1: extra data
216 * @str2: extra data
217 *
218 * Handle a parser error
219 */
220static void
221xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
222 const char *msg, const xmlChar * str1, const xmlChar * str2)
223{
224 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *data = NULL;
227
228 if (ctxt != NULL) {
229 ctxt->nberrors++;
230 channel = ctxt->error;
231 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000232 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000233 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000234 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 error, XML_ERR_ERROR, NULL, 0,
236 (const char *) str1, (const char *) str2, NULL, 0, 0,
237 msg, str1, str2);
238}
239
240/**
241 * xmlSchemaPErr2:
242 * @ctxt: the parsing context
243 * @node: the context node
244 * @node: the current child
245 * @error: the error code
246 * @msg: the error message
247 * @str1: extra data
248 * @str2: extra data
249 *
250 * Handle a parser error
251 */
252static void
253xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
254 xmlNodePtr child, int error,
255 const char *msg, const xmlChar * str1, const xmlChar * str2)
256{
257 if (child != NULL)
258 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
259 else
260 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
261}
262
263/**
264 * xmlSchemaVTypeErrMemory:
265 * @node: a context node
266 * @extra: extra informations
267 *
268 * Handle an out of memory condition
269 */
270static void
271xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
272 const char *extra, xmlNodePtr node)
273{
274 if (ctxt != NULL) {
275 ctxt->nberrors++;
276 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
277 }
278 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
279 extra);
280}
281
282/**
283 * xmlSchemaVErr3:
284 * @ctxt: the validation context
285 * @node: the context node
286 * @error: the error code
287 * @msg: the error message
288 * @str1: extra data
289 * @str2: extra data
290 * @str3: extra data
291 *
292 * Handle a validation error
293 */
294static void
295xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
296 const char *msg, const xmlChar *str1, const xmlChar *str2,
297 const xmlChar *str3)
298{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000299 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000300 xmlGenericErrorFunc channel = NULL;
301 void *data = NULL;
302
303 if (ctxt != NULL) {
304 ctxt->nberrors++;
305 ctxt->err = error;
306 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000307 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000308 data = ctxt->userData;
309 }
310 /* reajust to global error numbers */
311 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000312 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000313 error, XML_ERR_ERROR, NULL, 0,
314 (const char *) str1, (const char *) str2,
315 (const char *) str3, 0, 0,
316 msg, str1, str2, str3);
317}
318/**
319 * xmlSchemaVErr:
320 * @ctxt: the validation context
321 * @node: the context node
322 * @error: the error code
323 * @msg: the error message
324 * @str1: extra data
325 * @str2: extra data
326 *
327 * Handle a validation error
328 */
329static void
330xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
331 const char *msg, const xmlChar * str1, const xmlChar * str2)
332{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000333 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000334 xmlGenericErrorFunc channel = NULL;
335 void *data = NULL;
336
337 if (ctxt != NULL) {
338 ctxt->nberrors++;
339 ctxt->err = error;
340 channel = ctxt->error;
341 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000342 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000343 }
344 /* reajust to global error numbers */
345 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000346 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000347 error, XML_ERR_ERROR, NULL, 0,
348 (const char *) str1, (const char *) str2, NULL, 0, 0,
349 msg, str1, str2);
350}
Daniel Veillard4255d502002-04-16 15:50:10 +0000351
352/************************************************************************
353 * *
354 * Allocation functions *
355 * *
356 ************************************************************************/
357
358/**
359 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000360 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000361 *
362 * Allocate a new Schema structure.
363 *
364 * Returns the newly allocated structure or NULL in case or error
365 */
366static xmlSchemaPtr
367xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
368{
369 xmlSchemaPtr ret;
370
371 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
372 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000373 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000374 return (NULL);
375 }
376 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000377 xmlDictReference(ctxt->dict);
378 ret->dict = ctxt->dict;
Daniel Veillard4255d502002-04-16 15:50:10 +0000379
380 return (ret);
381}
382
383/**
384 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000385 *
386 * Allocate a new Facet structure.
387 *
388 * Returns the newly allocated structure or NULL in case or error
389 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000390xmlSchemaFacetPtr
391xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000392{
393 xmlSchemaFacetPtr ret;
394
395 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
396 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000397 return (NULL);
398 }
399 memset(ret, 0, sizeof(xmlSchemaFacet));
400
401 return (ret);
402}
403
404/**
405 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000406 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000407 * @node: a node
408 *
409 * Allocate a new annotation structure.
410 *
411 * Returns the newly allocated structure or NULL in case or error
412 */
413static xmlSchemaAnnotPtr
414xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
415{
416 xmlSchemaAnnotPtr ret;
417
418 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
419 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000420 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000421 return (NULL);
422 }
423 memset(ret, 0, sizeof(xmlSchemaAnnot));
424 ret->content = node;
425 return (ret);
426}
427
428/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000429 * xmlSchemaFreeAnnot:
430 * @annot: a schema type structure
431 *
432 * Deallocate a annotation structure
433 */
434static void
435xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
436{
437 if (annot == NULL)
438 return;
439 xmlFree(annot);
440}
441
442/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000443 * xmlSchemaFreeImport:
444 * @import: a schema import structure
445 *
446 * Deallocate an import structure
447 */
448static void
449xmlSchemaFreeImport(xmlSchemaImportPtr import)
450{
451 if (import == NULL)
452 return;
453
454 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000455 xmlFree(import);
456}
457
458/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000459 * xmlSchemaFreeInclude:
460 * @include: a schema include structure
461 *
462 * Deallocate an include structure
463 */
464static void
465xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
466{
467 if (include == NULL)
468 return;
469
470 xmlFreeDoc(include->doc);
471 xmlFree(include);
472}
473
474/**
475 * xmlSchemaFreeIncludeList:
476 * @includes: a schema include list
477 *
478 * Deallocate an include structure
479 */
480static void
481xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
482{
483 xmlSchemaIncludePtr next;
484
485 while (includes != NULL) {
486 next = includes->next;
487 xmlSchemaFreeInclude(includes);
488 includes = next;
489 }
490}
491
492/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000493 * xmlSchemaFreeNotation:
494 * @schema: a schema notation structure
495 *
496 * Deallocate a Schema Notation structure.
497 */
498static void
499xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
500{
501 if (nota == NULL)
502 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000503 xmlFree(nota);
504}
505
506/**
507 * xmlSchemaFreeAttribute:
508 * @schema: a schema attribute structure
509 *
510 * Deallocate a Schema Attribute structure.
511 */
512static void
513xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
514{
515 if (attr == NULL)
516 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000517 xmlFree(attr);
518}
519
520/**
521 * xmlSchemaFreeAttributeGroup:
522 * @schema: a schema attribute group structure
523 *
524 * Deallocate a Schema Attribute Group structure.
525 */
526static void
527xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
528{
529 if (attr == NULL)
530 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000531 xmlFree(attr);
532}
533
534/**
535 * xmlSchemaFreeElement:
536 * @schema: a schema element structure
537 *
538 * Deallocate a Schema Element structure.
539 */
540static void
541xmlSchemaFreeElement(xmlSchemaElementPtr elem)
542{
543 if (elem == NULL)
544 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000545 if (elem->annot != NULL)
546 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000547 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000548 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000549 xmlFree(elem);
550}
551
552/**
553 * xmlSchemaFreeFacet:
554 * @facet: a schema facet structure
555 *
556 * Deallocate a Schema Facet structure.
557 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000558void
Daniel Veillard4255d502002-04-16 15:50:10 +0000559xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
560{
561 if (facet == NULL)
562 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000563 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000564 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000565 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000566 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000567 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000568 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000569 xmlFree(facet);
570}
571
572/**
573 * xmlSchemaFreeType:
574 * @type: a schema type structure
575 *
576 * Deallocate a Schema Type structure.
577 */
578void
579xmlSchemaFreeType(xmlSchemaTypePtr type)
580{
581 if (type == NULL)
582 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000583 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000584 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000585 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000586 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000587
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000588 facet = type->facets;
589 while (facet != NULL) {
590 next = facet->next;
591 xmlSchemaFreeFacet(facet);
592 facet = next;
593 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000594 }
595 xmlFree(type);
596}
597
598/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000599 * xmlSchemaFreeTypeList:
600 * @type: a schema type structure
601 *
602 * Deallocate a Schema Type structure.
603 */
604static void
605xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
606{
607 xmlSchemaTypePtr next;
608
609 while (type != NULL) {
610 next = type->redef;
611 xmlSchemaFreeType(type);
612 type = next;
613 }
614}
615
616/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000617 * xmlSchemaFree:
618 * @schema: a schema structure
619 *
620 * Deallocate a Schema structure.
621 */
622void
623xmlSchemaFree(xmlSchemaPtr schema)
624{
625 if (schema == NULL)
626 return;
627
Daniel Veillard4255d502002-04-16 15:50:10 +0000628 if (schema->notaDecl != NULL)
629 xmlHashFree(schema->notaDecl,
630 (xmlHashDeallocator) xmlSchemaFreeNotation);
631 if (schema->attrDecl != NULL)
632 xmlHashFree(schema->attrDecl,
633 (xmlHashDeallocator) xmlSchemaFreeAttribute);
634 if (schema->attrgrpDecl != NULL)
635 xmlHashFree(schema->attrgrpDecl,
636 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
637 if (schema->elemDecl != NULL)
638 xmlHashFree(schema->elemDecl,
639 (xmlHashDeallocator) xmlSchemaFreeElement);
640 if (schema->typeDecl != NULL)
641 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000642 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000643 if (schema->groupDecl != NULL)
644 xmlHashFree(schema->groupDecl,
645 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000646 if (schema->schemasImports != NULL)
647 xmlHashFree(schema->schemasImports,
648 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000649 if (schema->includes != NULL) {
650 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
651 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000652 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000653 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000654 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000655 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000656 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000657
658 xmlFree(schema);
659}
660
661/************************************************************************
662 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000663 * Debug functions *
664 * *
665 ************************************************************************/
666
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000667#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000668
Daniel Veillard4255d502002-04-16 15:50:10 +0000669/**
670 * xmlSchemaElementDump:
671 * @elem: an element
672 * @output: the file output
673 *
674 * Dump the element
675 */
676static void
677xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000678 const xmlChar * name ATTRIBUTE_UNUSED,
679 const xmlChar * context ATTRIBUTE_UNUSED,
680 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000681{
682 if (elem == NULL)
683 return;
684
685 fprintf(output, "Element ");
686 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000687 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000688 fprintf(output, ": %s ", elem->name);
689 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000690 fprintf(output, "namespace '%s' ", namespace);
691
Daniel Veillard4255d502002-04-16 15:50:10 +0000692 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000693 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000694 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000695 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000696 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000697 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000698 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000699 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000700 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000701 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000702 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000703 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000704 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000706 fprintf(output, "\n");
707 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000708 fprintf(output, " ");
709 if (elem->minOccurs != 1)
710 fprintf(output, "min: %d ", elem->minOccurs);
711 if (elem->maxOccurs >= UNBOUNDED)
712 fprintf(output, "max: unbounded\n");
713 else if (elem->maxOccurs != 1)
714 fprintf(output, "max: %d\n", elem->maxOccurs);
715 else
716 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000717 }
718 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000719 fprintf(output, " type: %s", elem->namedType);
720 if (elem->namedTypeNs != NULL)
721 fprintf(output, " ns %s\n", elem->namedTypeNs);
722 else
723 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000724 }
725 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000726 fprintf(output, " substitutionGroup: %s", elem->substGroup);
727 if (elem->substGroupNs != NULL)
728 fprintf(output, " ns %s\n", elem->substGroupNs);
729 else
730 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000731 }
732 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000733 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000734}
735
736/**
737 * xmlSchemaAnnotDump:
738 * @output: the file output
739 * @annot: a annotation
740 *
741 * Dump the annotation
742 */
743static void
744xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
745{
746 xmlChar *content;
747
748 if (annot == NULL)
749 return;
750
751 content = xmlNodeGetContent(annot->content);
752 if (content != NULL) {
753 fprintf(output, " Annot: %s\n", content);
754 xmlFree(content);
755 } else
756 fprintf(output, " Annot: empty\n");
757}
758
759/**
760 * xmlSchemaTypeDump:
761 * @output: the file output
762 * @type: a type structure
763 *
764 * Dump a SchemaType structure
765 */
766static void
767xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
768{
769 if (type == NULL) {
770 fprintf(output, "Type: NULL\n");
771 return;
772 }
773 fprintf(output, "Type: ");
774 if (type->name != NULL)
775 fprintf(output, "%s, ", type->name);
776 else
777 fprintf(output, "no name");
778 switch (type->type) {
779 case XML_SCHEMA_TYPE_BASIC:
780 fprintf(output, "basic ");
781 break;
782 case XML_SCHEMA_TYPE_SIMPLE:
783 fprintf(output, "simple ");
784 break;
785 case XML_SCHEMA_TYPE_COMPLEX:
786 fprintf(output, "complex ");
787 break;
788 case XML_SCHEMA_TYPE_SEQUENCE:
789 fprintf(output, "sequence ");
790 break;
791 case XML_SCHEMA_TYPE_CHOICE:
792 fprintf(output, "choice ");
793 break;
794 case XML_SCHEMA_TYPE_ALL:
795 fprintf(output, "all ");
796 break;
797 case XML_SCHEMA_TYPE_UR:
798 fprintf(output, "ur ");
799 break;
800 case XML_SCHEMA_TYPE_RESTRICTION:
801 fprintf(output, "restriction ");
802 break;
803 case XML_SCHEMA_TYPE_EXTENSION:
804 fprintf(output, "extension ");
805 break;
806 default:
807 fprintf(output, "unknowntype%d ", type->type);
808 break;
809 }
810 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000811 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000812 }
813 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000814 case XML_SCHEMA_CONTENT_UNKNOWN:
815 fprintf(output, "unknown ");
816 break;
817 case XML_SCHEMA_CONTENT_EMPTY:
818 fprintf(output, "empty ");
819 break;
820 case XML_SCHEMA_CONTENT_ELEMENTS:
821 fprintf(output, "element ");
822 break;
823 case XML_SCHEMA_CONTENT_MIXED:
824 fprintf(output, "mixed ");
825 break;
826 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
827 fprintf(output, "mixed_or_elems ");
828 break;
829 case XML_SCHEMA_CONTENT_BASIC:
830 fprintf(output, "basic ");
831 break;
832 case XML_SCHEMA_CONTENT_SIMPLE:
833 fprintf(output, "simple ");
834 break;
835 case XML_SCHEMA_CONTENT_ANY:
836 fprintf(output, "any ");
837 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000838 }
839 fprintf(output, "\n");
840 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000841 fprintf(output, " ");
842 if (type->minOccurs != 1)
843 fprintf(output, "min: %d ", type->minOccurs);
844 if (type->maxOccurs >= UNBOUNDED)
845 fprintf(output, "max: unbounded\n");
846 else if (type->maxOccurs != 1)
847 fprintf(output, "max: %d\n", type->maxOccurs);
848 else
849 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000850 }
851 if (type->annot != NULL)
852 xmlSchemaAnnotDump(output, type->annot);
853 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000854 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000855
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000856 fprintf(output, " subtypes: ");
857 while (sub != NULL) {
858 fprintf(output, "%s ", sub->name);
859 sub = sub->next;
860 }
861 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000862 }
863
864}
865
866/**
867 * xmlSchemaDump:
868 * @output: the file output
869 * @schema: a schema structure
870 *
871 * Dump a Schema structure.
872 */
873void
874xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
875{
876 if (schema == NULL) {
877 fprintf(output, "Schemas: NULL\n");
878 return;
879 }
880 fprintf(output, "Schemas: ");
881 if (schema->name != NULL)
882 fprintf(output, "%s, ", schema->name);
883 else
884 fprintf(output, "no name, ");
885 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000886 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000887 else
888 fprintf(output, "no target namespace");
889 fprintf(output, "\n");
890 if (schema->annot != NULL)
891 xmlSchemaAnnotDump(output, schema->annot);
892
893 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
894 output);
895 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000896 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000897}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000898#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000899
900/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000901 * *
902 * Utilities *
903 * *
904 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000905
906/**
907 * xmlSchemaGetProp:
908 * @ctxt: the parser context
909 * @node: the node
910 * @name: the property name
911 *
912 * Read a attribute value and internalize the string
913 *
914 * Returns the string or NULL if not present.
915 */
916static const xmlChar *
917xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
918 const char *name)
919{
920 xmlChar *val;
921 const xmlChar *ret;
922
923 val = xmlGetProp(node, BAD_CAST name);
924 if (val == NULL)
925 return(NULL);
926 ret = xmlDictLookup(ctxt->dict, val, -1);
927 xmlFree(val);
928 return(ret);
929}
930
931/**
932 * xmlSchemaGetNamespace:
933 * @ctxt: the parser context
934 * @schema: the schemas containing the declaration
935 * @node: the node
936 * @qname: the QName to analyze
937 *
938 * Find the namespace name for the given declaration.
939 *
940 * Returns the local name for that declaration, as well as the namespace name
941 */
942static const xmlChar *
943xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
944 xmlNodePtr node, const xmlChar *qname,
945 const xmlChar **namespace) {
946 int len;
947 const xmlChar *name, *prefix, *def = NULL;
948 xmlNsPtr ns;
949
950 *namespace = NULL;
951
952 if (xmlStrEqual(node->name, BAD_CAST "element") ||
953 xmlStrEqual(node->name, BAD_CAST "attribute") ||
954 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
955 xmlStrEqual(node->name, BAD_CAST "complexType")) {
956 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
957 }
958
959 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
960 name = xmlSplitQName3(qname, &len);
961 if (name == NULL) {
962 if (def == NULL) {
963 if (xmlStrEqual(node->name, BAD_CAST "element")) {
964 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
965 *namespace = schema->targetNamespace;
966 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
967 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
968 *namespace = schema->targetNamespace;
969 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
970 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
971 *namespace = schema->targetNamespace;
972 }
973 } else {
974 *namespace = def;
975 }
976 return(qname);
977 }
978 name = xmlDictLookup(ctxt->dict, name, -1);
979 prefix = xmlDictLookup(ctxt->dict, qname, len);
980 if (def != NULL) {
981 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
982 "%s: presence of both prefix %s and targetNamespace\n",
983 node->name, prefix);
984 }
985 ns = xmlSearchNs(node->doc, node, prefix);
986 if (ns == NULL) {
987 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
988 "%s: the QName prefix %s is undefined\n",
989 node->name, prefix);
990 return(name);
991 }
992 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
993 return(name);
994}
995
996/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +0000997 * *
998 * Parsing functions *
999 * *
1000 ************************************************************************/
1001
1002/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001003 * xmlSchemaGetElem:
1004 * @schema: the schemas context
1005 * @name: the element name
1006 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001007 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001008 *
1009 * Lookup a an element in the schemas or the accessible schemas
1010 *
1011 * Returns the element definition or NULL if not found.
1012 */
1013static xmlSchemaElementPtr
1014xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001015 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001016{
1017 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001018 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001019
1020 if ((name == NULL) || (schema == NULL))
1021 return (NULL);
1022
1023 if (namespace == NULL) {
1024 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001025 if ((ret != NULL) &&
1026 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001027 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001028 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001029 } else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
1030 if (xmlStrEqual(namespace, schema->targetNamespace))
1031 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1032 else
1033 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001034 if ((ret != NULL) &&
1035 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001036 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001037 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001038 } 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 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001045 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001046 import = xmlHashLookup(schema->schemasImports, namespace);
1047 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001048 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001049#ifdef DEBUG
1050 if (ret == NULL) {
1051 if (namespace == NULL)
1052 fprintf(stderr, "Unable to lookup type %s", name);
1053 else
1054 fprintf(stderr, "Unable to lookup type %s:%s", name,
1055 namespace);
1056 }
1057#endif
1058 return (ret);
1059}
1060
1061/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001062 * xmlSchemaGetType:
1063 * @schema: the schemas context
1064 * @name: the type name
1065 * @ns: the type namespace
1066 *
1067 * Lookup a type in the schemas or the predefined types
1068 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001069 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001070 */
1071static xmlSchemaTypePtr
1072xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001073 const xmlChar * namespace)
1074{
Daniel Veillard4255d502002-04-16 15:50:10 +00001075 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001076 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001077
1078 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001079 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001080 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001081 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1082 if (ret != NULL)
1083 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001084 }
1085 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001086 if (ret != NULL)
1087 return (ret);
1088 import = xmlHashLookup(schema->schemasImports, namespace);
1089 if (import != NULL)
1090 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001091#ifdef DEBUG
1092 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001093 if (namespace == NULL)
1094 fprintf(stderr, "Unable to lookup type %s", name);
1095 else
1096 fprintf(stderr, "Unable to lookup type %s:%s", name,
1097 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001098 }
1099#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001100 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001101}
1102
1103/************************************************************************
1104 * *
1105 * Parsing functions *
1106 * *
1107 ************************************************************************/
1108
1109#define IS_BLANK_NODE(n) \
1110 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1111
1112/**
1113 * xmlSchemaIsBlank:
1114 * @str: a string
1115 *
1116 * Check if a string is ignorable
1117 *
1118 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1119 */
1120static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001121xmlSchemaIsBlank(xmlChar * str)
1122{
Daniel Veillard4255d502002-04-16 15:50:10 +00001123 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001124 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001125 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001126 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001127 return (0);
1128 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001129 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001130 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001131}
1132
1133/**
1134 * xmlSchemaAddNotation:
1135 * @ctxt: a schema validation context
1136 * @schema: the schema being built
1137 * @name: the item name
1138 *
1139 * Add an XML schema Attrribute declaration
1140 * *WARNING* this interface is highly subject to change
1141 *
1142 * Returns the new struture or NULL in case of error
1143 */
1144static xmlSchemaNotationPtr
1145xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001146 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001147{
1148 xmlSchemaNotationPtr ret = NULL;
1149 int val;
1150
1151 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1152 return (NULL);
1153
1154 if (schema->notaDecl == NULL)
1155 schema->notaDecl = xmlHashCreate(10);
1156 if (schema->notaDecl == NULL)
1157 return (NULL);
1158
1159 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1160 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001161 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001162 return (NULL);
1163 }
1164 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001165 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001166 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1167 ret);
1168 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001169 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1170 XML_SCHEMAP_REDEFINED_NOTATION,
1171 "Notation %s already defined\n",
1172 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001173 xmlFree(ret);
1174 return (NULL);
1175 }
1176 return (ret);
1177}
1178
1179
1180/**
1181 * xmlSchemaAddAttribute:
1182 * @ctxt: a schema validation context
1183 * @schema: the schema being built
1184 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001185 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001186 *
1187 * Add an XML schema Attrribute declaration
1188 * *WARNING* this interface is highly subject to change
1189 *
1190 * Returns the new struture or NULL in case of error
1191 */
1192static xmlSchemaAttributePtr
1193xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001194 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001195{
1196 xmlSchemaAttributePtr ret = NULL;
1197 int val;
1198
1199 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1200 return (NULL);
1201
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001202#ifdef DEBUG
1203 fprintf(stderr, "Adding attribute %s\n", name);
1204 if (namespace != NULL)
1205 fprintf(stderr, " target namespace %s\n", namespace);
1206#endif
1207
Daniel Veillard4255d502002-04-16 15:50:10 +00001208 if (schema->attrDecl == NULL)
1209 schema->attrDecl = xmlHashCreate(10);
1210 if (schema->attrDecl == NULL)
1211 return (NULL);
1212
1213 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1214 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001215 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001216 return (NULL);
1217 }
1218 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001219 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1220 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001221 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001222 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001223 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001224 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1225 XML_SCHEMAP_REDEFINED_ATTR,
1226 "Attribute %s already defined\n",
1227 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001228 xmlFree(ret);
1229 return (NULL);
1230 }
1231 return (ret);
1232}
1233
1234/**
1235 * xmlSchemaAddAttributeGroup:
1236 * @ctxt: a schema validation context
1237 * @schema: the schema being built
1238 * @name: the item name
1239 *
1240 * Add an XML schema Attrribute Group declaration
1241 *
1242 * Returns the new struture or NULL in case of error
1243 */
1244static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001245xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1246 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001247{
1248 xmlSchemaAttributeGroupPtr ret = NULL;
1249 int val;
1250
1251 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1252 return (NULL);
1253
1254 if (schema->attrgrpDecl == NULL)
1255 schema->attrgrpDecl = xmlHashCreate(10);
1256 if (schema->attrgrpDecl == NULL)
1257 return (NULL);
1258
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001259 ret =
1260 (xmlSchemaAttributeGroupPtr)
1261 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001262 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001263 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001264 return (NULL);
1265 }
1266 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001267 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001268 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001269 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001270 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001271 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1272 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1273 "Attribute group %s already defined\n",
1274 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001275 xmlFree(ret);
1276 return (NULL);
1277 }
1278 return (ret);
1279}
1280
1281/**
1282 * xmlSchemaAddElement:
1283 * @ctxt: a schema validation context
1284 * @schema: the schema being built
1285 * @name: the type name
1286 * @namespace: the type namespace
1287 *
1288 * Add an XML schema Element declaration
1289 * *WARNING* this interface is highly subject to change
1290 *
1291 * Returns the new struture or NULL in case of error
1292 */
1293static xmlSchemaElementPtr
1294xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1295 const xmlChar * name, const xmlChar * namespace)
1296{
1297 xmlSchemaElementPtr ret = NULL;
1298 int val;
1299
1300 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1301 return (NULL);
1302
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001303#ifdef DEBUG
1304 fprintf(stderr, "Adding element %s\n", name);
1305 if (namespace != NULL)
1306 fprintf(stderr, " target namespace %s\n", namespace);
1307#endif
1308
Daniel Veillard4255d502002-04-16 15:50:10 +00001309 if (schema->elemDecl == NULL)
1310 schema->elemDecl = xmlHashCreate(10);
1311 if (schema->elemDecl == NULL)
1312 return (NULL);
1313
1314 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1315 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001316 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001317 return (NULL);
1318 }
1319 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001320 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1321 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001322 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001323 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001324 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001325 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001326
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001327 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001328 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1329 namespace, ret);
1330 if (val != 0) {
1331 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1332 XML_SCHEMAP_REDEFINED_ELEMENT,
1333 "Element %s already defined\n",
1334 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001335 xmlFree(ret);
1336 return (NULL);
1337 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001338 }
1339 return (ret);
1340}
1341
1342/**
1343 * xmlSchemaAddType:
1344 * @ctxt: a schema validation context
1345 * @schema: the schema being built
1346 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001347 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001348 *
1349 * Add an XML schema Simple Type definition
1350 * *WARNING* this interface is highly subject to change
1351 *
1352 * Returns the new struture or NULL in case of error
1353 */
1354static xmlSchemaTypePtr
1355xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001356 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001357{
1358 xmlSchemaTypePtr ret = NULL;
1359 int val;
1360
1361 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1362 return (NULL);
1363
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001364#ifdef DEBUG
1365 fprintf(stderr, "Adding type %s\n", name);
1366 if (namespace != NULL)
1367 fprintf(stderr, " target namespace %s\n", namespace);
1368#endif
1369
Daniel Veillard4255d502002-04-16 15:50:10 +00001370 if (schema->typeDecl == NULL)
1371 schema->typeDecl = xmlHashCreate(10);
1372 if (schema->typeDecl == NULL)
1373 return (NULL);
1374
1375 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1376 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001377 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001378 return (NULL);
1379 }
1380 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001381 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001382 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001383 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001384 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001385 if (ctxt->includes == 0) {
1386 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1387 XML_SCHEMAP_REDEFINED_TYPE,
1388 "Type %s already defined\n",
1389 name, NULL);
1390 xmlFree(ret);
1391 return (NULL);
1392 } else {
1393 xmlSchemaTypePtr prev;
1394
1395 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1396 if (prev == NULL) {
1397 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1398 XML_ERR_INTERNAL_ERROR,
1399 "Internal error on type %s definition\n",
1400 name, NULL);
1401 xmlFree(ret);
1402 return (NULL);
1403 }
1404 ret->redef = prev->redef;
1405 prev->redef = ret;
1406 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001407 }
1408 ret->minOccurs = 1;
1409 ret->maxOccurs = 1;
1410
1411 return (ret);
1412}
1413
1414/**
1415 * xmlSchemaAddGroup:
1416 * @ctxt: a schema validation context
1417 * @schema: the schema being built
1418 * @name: the group name
1419 *
1420 * Add an XML schema Group definition
1421 *
1422 * Returns the new struture or NULL in case of error
1423 */
1424static xmlSchemaTypePtr
1425xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001426 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001427{
1428 xmlSchemaTypePtr ret = NULL;
1429 int val;
1430
1431 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1432 return (NULL);
1433
1434 if (schema->groupDecl == NULL)
1435 schema->groupDecl = xmlHashCreate(10);
1436 if (schema->groupDecl == NULL)
1437 return (NULL);
1438
1439 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1440 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001441 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001442 return (NULL);
1443 }
1444 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001445 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001446 val =
1447 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1448 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001449 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001450 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1451 XML_SCHEMAP_REDEFINED_GROUP,
1452 "Group %s already defined\n",
1453 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001454 xmlFree(ret);
1455 return (NULL);
1456 }
1457 ret->minOccurs = 1;
1458 ret->maxOccurs = 1;
1459
1460 return (ret);
1461}
1462
1463/************************************************************************
1464 * *
1465 * Utilities for parsing *
1466 * *
1467 ************************************************************************/
1468
1469/**
1470 * xmlGetQNameProp:
1471 * @ctxt: a schema validation context
1472 * @node: a subtree containing XML Schema informations
1473 * @name: the attribute name
1474 * @namespace: the result namespace if any
1475 *
1476 * Extract a QName Attribute value
1477 *
1478 * Returns the NCName or NULL if not found, and also update @namespace
1479 * with the namespace URI
1480 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001481static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001482xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001483 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001484{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001485 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001486 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001487 const xmlChar *ret, *prefix;
1488 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001489
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001490 *namespace = NULL;
1491 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001492 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001493 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001494
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001495 ret = xmlSplitQName3(val, &len);
1496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001497 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001498 }
1499 ret = xmlDictLookup(ctxt->dict, ret, -1);
1500 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001501
1502 ns = xmlSearchNs(node->doc, node, prefix);
1503 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001504 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1505 "Attribute %s: the QName prefix %s is undefined\n",
1506 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001507 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001508 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001509 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001510 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001511}
1512
1513/**
1514 * xmlGetMaxOccurs:
1515 * @ctxt: a schema validation context
1516 * @node: a subtree containing XML Schema informations
1517 *
1518 * Get the maxOccurs property
1519 *
1520 * Returns the default if not found, or the value
1521 */
1522static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001523xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1524{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001525 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001526 int ret = 0;
1527
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001528 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001529 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001530 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001531
1532 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001533 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001534 }
1535
1536 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001537 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001538 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001539 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001540 ret = ret * 10 + (*cur - '0');
1541 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001542 }
William M. Brack76e95df2003-10-18 16:20:14 +00001543 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001544 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001545 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001546 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1547 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001548 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001549 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001550 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001551}
1552
1553/**
1554 * xmlGetMinOccurs:
1555 * @ctxt: a schema validation context
1556 * @node: a subtree containing XML Schema informations
1557 *
1558 * Get the minOccurs property
1559 *
1560 * Returns the default if not found, or the value
1561 */
1562static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001563xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1564{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001565 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001566 int ret = 0;
1567
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001568 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001569 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001570 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001571
1572 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001573 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001574 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001575 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576 ret = ret * 10 + (*cur - '0');
1577 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001578 }
William M. Brack76e95df2003-10-18 16:20:14 +00001579 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001580 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001581 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001582 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1583 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001584 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001585 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001586 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001587}
1588
1589/**
1590 * xmlGetBooleanProp:
1591 * @ctxt: a schema validation context
1592 * @node: a subtree containing XML Schema informations
1593 * @name: the attribute name
1594 * @def: the default value
1595 *
1596 * Get is a bolean property is set
1597 *
1598 * Returns the default if not found, 0 if found to be false,
1599 * 1 if found to be true
1600 */
1601static int
1602xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001603 const char *name, int def)
1604{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001605 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001606
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001607 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001608 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001609 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001610
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001611 if (xmlStrEqual(val, BAD_CAST "true"))
1612 def = 1;
1613 else if (xmlStrEqual(val, BAD_CAST "false"))
1614 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001615 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1617 "Attribute %s: the value %s is not boolean\n",
1618 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001619 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001620 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001621}
1622
1623/************************************************************************
1624 * *
1625 * Shema extraction from an Infoset *
1626 * *
1627 ************************************************************************/
1628static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1629 ctxt, xmlSchemaPtr schema,
1630 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001631static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1632 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001633 xmlSchemaPtr schema,
1634 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001635static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1636 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001637 xmlSchemaPtr schema,
1638 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001639 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001640static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1641 xmlSchemaPtr schema,
1642 xmlNodePtr node);
1643static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1644 xmlSchemaPtr schema,
1645 xmlNodePtr node);
1646static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1647 ctxt,
1648 xmlSchemaPtr schema,
1649 xmlNodePtr node);
1650static xmlSchemaAttributeGroupPtr
1651xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1652 xmlSchemaPtr schema, xmlNodePtr node);
1653static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1654 xmlSchemaPtr schema,
1655 xmlNodePtr node);
1656static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1657 xmlSchemaPtr schema,
1658 xmlNodePtr node);
1659static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001660xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1661 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001662
1663/**
1664 * xmlSchemaParseAttrDecls:
1665 * @ctxt: a schema validation context
1666 * @schema: the schema being built
1667 * @node: a subtree containing XML Schema informations
1668 * @type: the hosting type
1669 *
1670 * parse a XML schema attrDecls declaration corresponding to
1671 * <!ENTITY % attrDecls
1672 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1673 */
1674static xmlNodePtr
1675xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1676 xmlNodePtr child, xmlSchemaTypePtr type)
1677{
1678 xmlSchemaAttributePtr lastattr, attr;
1679
1680 lastattr = NULL;
1681 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001682 (IS_SCHEMA(child, "attributeGroup"))) {
1683 attr = NULL;
1684 if (IS_SCHEMA(child, "attribute")) {
1685 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1686 } else if (IS_SCHEMA(child, "attributeGroup")) {
1687 attr = (xmlSchemaAttributePtr)
1688 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1689 }
1690 if (attr != NULL) {
1691 if (lastattr == NULL) {
1692 type->attributes = attr;
1693 lastattr = attr;
1694 } else {
1695 lastattr->next = attr;
1696 lastattr = attr;
1697 }
1698 }
1699 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001700 }
1701 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001702 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
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 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001714 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001715}
1716
1717/**
1718 * xmlSchemaParseAnnotation:
1719 * @ctxt: a schema validation context
1720 * @schema: the schema being built
1721 * @node: a subtree containing XML Schema informations
1722 *
1723 * parse a XML schema Attrribute declaration
1724 * *WARNING* this interface is highly subject to change
1725 *
1726 * Returns -1 in case of error, 0 if the declaration is inproper and
1727 * 1 in case of success.
1728 */
1729static xmlSchemaAnnotPtr
1730xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1731 xmlNodePtr node)
1732{
1733 xmlSchemaAnnotPtr ret;
1734
1735 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1736 return (NULL);
1737 ret = xmlSchemaNewAnnot(ctxt, node);
1738
1739 return (ret);
1740}
1741
1742/**
1743 * xmlSchemaParseFacet:
1744 * @ctxt: a schema validation context
1745 * @schema: the schema being built
1746 * @node: a subtree containing XML Schema informations
1747 *
1748 * parse a XML schema Facet declaration
1749 * *WARNING* this interface is highly subject to change
1750 *
1751 * Returns the new type structure or NULL in case of error
1752 */
1753static xmlSchemaFacetPtr
1754xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001755 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001756{
1757 xmlSchemaFacetPtr facet;
1758 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001759 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001760
1761 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1762 return (NULL);
1763
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001764 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001765 if (facet == NULL) {
1766 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1767 return (NULL);
1768 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001769 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001770 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001771 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001772 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1773 "Facet %s has no value\n", node->name, NULL);
1774 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001775 return (NULL);
1776 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001777 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001778 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001779 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001780 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001781 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001782 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001783 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001784 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001785 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001786 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001787 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001788 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001789 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001790 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001791 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001792 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001793 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001794 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001795 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001796 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001797 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001798 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1799 } else if (IS_SCHEMA(node, "minLength")) {
1800 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1801 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001802 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1803 "Unknown facet type %s\n", node->name, NULL);
1804 xmlSchemaFreeFacet(facet);
1805 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001807 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001808 facet->value = value;
1809 child = node->children;
1810
1811 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001812 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1813 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001814 }
1815 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001816 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1817 "Facet %s has unexpected child content\n",
1818 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 }
1820 return (facet);
1821}
1822
1823/**
1824 * xmlSchemaParseAny:
1825 * @ctxt: a schema validation context
1826 * @schema: the schema being built
1827 * @node: a subtree containing XML Schema informations
1828 *
1829 * parse a XML schema Any declaration
1830 * *WARNING* this interface is highly subject to change
1831 *
1832 * Returns the new type structure or NULL in case of error
1833 */
1834static xmlSchemaTypePtr
1835xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1836 xmlNodePtr node)
1837{
1838 xmlSchemaTypePtr type;
1839 xmlNodePtr child = NULL;
1840 xmlChar name[30];
1841
1842 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1843 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001844 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001845 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001846 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001847 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001848 type->node = node;
1849 type->type = XML_SCHEMA_TYPE_ANY;
1850 child = node->children;
1851 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1852 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1853
1854 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001855 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1856 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001857 }
1858 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001859 xmlSchemaPErr2(ctxt, node, child,
1860 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1861 "Sequence %s has unexpected content\n", type->name,
1862 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001863 }
1864
1865 return (type);
1866}
1867
1868/**
1869 * xmlSchemaParseNotation:
1870 * @ctxt: a schema validation context
1871 * @schema: the schema being built
1872 * @node: a subtree containing XML Schema informations
1873 *
1874 * parse a XML schema Notation declaration
1875 *
1876 * Returns the new structure or NULL in case of error
1877 */
1878static xmlSchemaNotationPtr
1879xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001880 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001881{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001882 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001883 xmlSchemaNotationPtr ret;
1884 xmlNodePtr child = NULL;
1885
1886 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1887 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001888 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001889 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001890 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1891 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001892 return (NULL);
1893 }
1894 ret = xmlSchemaAddNotation(ctxt, schema, name);
1895 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001896 return (NULL);
1897 }
1898 child = node->children;
1899 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001900 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1901 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001902 }
1903 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001904 xmlSchemaPErr2(ctxt, node, child,
1905 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1906 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001907 }
1908
1909 return (ret);
1910}
1911
1912/**
1913 * xmlSchemaParseAnyAttribute:
1914 * @ctxt: a schema validation context
1915 * @schema: the schema being built
1916 * @node: a subtree containing XML Schema informations
1917 *
1918 * parse a XML schema AnyAttrribute declaration
1919 * *WARNING* this interface is highly subject to change
1920 *
1921 * Returns an attribute def structure or NULL
1922 */
1923static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001924xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1925 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001926{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001927 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001928 xmlSchemaAttributePtr ret;
1929 xmlNodePtr child = NULL;
1930 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001931 const xmlChar *local, *ns;
1932
Daniel Veillard4255d502002-04-16 15:50:10 +00001933
1934 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1935 return (NULL);
1936
1937 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001938 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1939 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001940 if (ret == NULL) {
1941 return (NULL);
1942 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001943 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1944 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001945 if ((processContents == NULL)
1946 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1947 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1948 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1949 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1950 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1951 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001952 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001953 xmlSchemaPErr2(ctxt, node, child,
1954 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1955 "anyAttribute has unexpected content for processContents: %s\n",
1956 processContents, NULL);
1957 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001958 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001959
1960 child = node->children;
1961 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001962 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1963 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001964 }
1965 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001966 xmlSchemaPErr2(ctxt, node, child,
1967 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1968 "anyAttribute %s has unexpected content\n",
1969 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001970 }
1971
1972 return (ret);
1973}
1974
1975
1976/**
1977 * xmlSchemaParseAttribute:
1978 * @ctxt: a schema validation context
1979 * @schema: the schema being built
1980 * @node: a subtree containing XML Schema informations
1981 *
1982 * parse a XML schema Attrribute declaration
1983 * *WARNING* this interface is highly subject to change
1984 *
1985 * Returns -1 in case of error, 0 if the declaration is inproper and
1986 * 1 in case of success.
1987 */
1988static xmlSchemaAttributePtr
1989xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1990 xmlNodePtr node)
1991{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001992 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001993 xmlSchemaAttributePtr ret;
1994 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001995 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001996
1997 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1998 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001999 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002000 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002001
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002002 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2003 if (ref == NULL) {
2004 xmlSchemaPErr2(ctxt, node, child,
2005 XML_SCHEMAP_ATTR_NONAME_NOREF,
2006 "Attribute has no name nor ref\n", NULL, NULL);
2007 return (NULL);
2008 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002009 if (refNs == NULL)
2010 refNs = schema->targetNamespace;
2011 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2012 name = (const xmlChar *) buf;
2013 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2014 } else {
2015 const xmlChar *local, *ns;
2016
2017 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2018 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002019 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002020 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002021 return (NULL);
2022 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002023 ret->ref = ref;
2024 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002025 if ((ret->targetNamespace != NULL) &&
2026 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2027 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2028 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002029 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002030 if ((ret->typeName != NULL) && (ret->typeNs == NULL))
2031 ret->typeNs = schema->targetNamespace;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002032 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002033 child = node->children;
2034 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002035 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2036 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002037 }
2038 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002039 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2040 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002041 }
2042 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002043 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2044 "attribute %s has unexpected content\n", name,
2045 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002046 }
2047
2048 return (ret);
2049}
2050
2051/**
2052 * xmlSchemaParseAttributeGroup:
2053 * @ctxt: a schema validation context
2054 * @schema: the schema being built
2055 * @node: a subtree containing XML Schema informations
2056 *
2057 * parse a XML schema Attribute Group declaration
2058 * *WARNING* this interface is highly subject to change
2059 *
2060 * Returns the attribute group or NULL in case of error.
2061 */
2062static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002063xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2064 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002065{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002066 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002067 xmlSchemaAttributeGroupPtr ret;
2068 xmlSchemaAttributePtr last = NULL, attr;
2069 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002070 const xmlChar *oldcontainer;
2071 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002072
2073 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2074 return (NULL);
2075 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002076 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002077 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002078
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002079 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2080 if (ref == NULL) {
2081 xmlSchemaPErr2(ctxt, node, child,
2082 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2083 "AttributeGroup has no name nor ref\n", NULL,
2084 NULL);
2085 return (NULL);
2086 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002087 if (refNs == NULL)
2088 refNs = schema->targetNamespace;
2089 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2090 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002091 if (name == NULL) {
2092 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2093 return (NULL);
2094 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002095 }
2096 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2097 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002098 return (NULL);
2099 }
2100 ret->ref = ref;
2101 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002102 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002103 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002104 child = node->children;
2105 ctxt->container = name;
2106 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002107 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2108 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002109 }
2110 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002111 (IS_SCHEMA(child, "attributeGroup"))) {
2112 attr = NULL;
2113 if (IS_SCHEMA(child, "attribute")) {
2114 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2115 } else if (IS_SCHEMA(child, "attributeGroup")) {
2116 attr = (xmlSchemaAttributePtr)
2117 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2118 }
2119 if (attr != NULL) {
2120 if (last == NULL) {
2121 ret->attributes = attr;
2122 last = attr;
2123 } else {
2124 last->next = attr;
2125 last = attr;
2126 }
2127 }
2128 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002129 }
2130 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002131 TODO
2132 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 }
2134 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002135 xmlSchemaPErr2(ctxt, node, child,
2136 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2137 "attribute group %s has unexpected content\n", name,
2138 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002139 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002140 ctxt->container = oldcontainer;
2141 return (ret);
2142}
2143
2144/**
2145 * xmlSchemaParseElement:
2146 * @ctxt: a schema validation context
2147 * @schema: the schema being built
2148 * @node: a subtree containing XML Schema informations
2149 *
2150 * parse a XML schema Element declaration
2151 * *WARNING* this interface is highly subject to change
2152 *
2153 * Returns -1 in case of error, 0 if the declaration is inproper and
2154 * 1 in case of success.
2155 */
2156static xmlSchemaElementPtr
2157xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2158 xmlNodePtr node, int toplevel)
2159{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002160 const xmlChar *name, *fixed;
2161 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002162 xmlSchemaElementPtr ret;
2163 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002164 const xmlChar *oldcontainer;
2165 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002166
2167 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2168 return (NULL);
2169 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002170 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002171 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002172
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002173 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2174 if (ref == NULL) {
2175 xmlSchemaPErr2(ctxt, node, child,
2176 XML_SCHEMAP_ELEM_NONAME_NOREF,
2177 "Element has no name nor ref\n", NULL, NULL);
2178 return (NULL);
2179 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002180 if (refNs == NULL)
2181 refNs = schema->targetNamespace;
2182 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2183 name = (const xmlChar *) buf;
2184 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2185 } else {
2186 const xmlChar *local, *ns;
2187
2188 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2189 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002190 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002191 if (ret != NULL)
2192 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002193 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002194 return (NULL);
2195 }
2196 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2197 ret->ref = ref;
2198 ret->refNs = refNs;
2199 if (ref != NULL)
2200 ret->flags |= XML_SCHEMAS_ELEM_REF;
2201 if (toplevel)
2202 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2203 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2204 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2205 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2206 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2207 ctxt->container = name;
2208
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002209 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002210 ret->namedType =
2211 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002212 if ((ret->namedType != NULL) && (ret->namedTypeNs == NULL))
2213 ret->namedTypeNs = schema->targetNamespace;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002214 ret->substGroup =
2215 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2216 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002217 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002218 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2219 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002220
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002221 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002222 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002223 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2224 "Element %s has both default and fixed\n",
2225 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002226 } else if (fixed != NULL) {
2227 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002229 }
2230
2231 child = node->children;
2232 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002233 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2234 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002235 }
2236 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002237 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002238 child = child->next;
2239 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002240 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002241 child = child->next;
2242 }
2243 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002244 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2245 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 }
2247 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2249 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002250 }
2251
2252 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002253 return (ret);
2254}
2255
2256/**
2257 * xmlSchemaParseUnion:
2258 * @ctxt: a schema validation context
2259 * @schema: the schema being built
2260 * @node: a subtree containing XML Schema informations
2261 *
2262 * parse a XML schema Union definition
2263 * *WARNING* this interface is highly subject to change
2264 *
2265 * Returns -1 in case of error, 0 if the declaration is inproper and
2266 * 1 in case of success.
2267 */
2268static xmlSchemaTypePtr
2269xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002270 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002271{
2272 xmlSchemaTypePtr type, subtype, last = NULL;
2273 xmlNodePtr child = NULL;
2274 xmlChar name[30];
2275
2276 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2277 return (NULL);
2278
2279
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002280 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002281 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002282 if (type == NULL)
2283 return (NULL);
2284 type->node = node;
2285 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002286 type->id = xmlSchemaGetProp(ctxt, node, "id");
2287 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002288
2289 child = node->children;
2290 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002291 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2292 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002293 }
2294 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002295 subtype = (xmlSchemaTypePtr)
2296 xmlSchemaParseSimpleType(ctxt, schema, child);
2297 if (subtype != NULL) {
2298 if (last == NULL) {
2299 type->subtypes = subtype;
2300 last = subtype;
2301 } else {
2302 last->next = subtype;
2303 last = subtype;
2304 }
2305 last->next = NULL;
2306 }
2307 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002308 }
2309 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002310 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2311 "Union %s has unexpected content\n", type->name,
2312 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002313 }
2314 return (type);
2315}
2316
2317/**
2318 * xmlSchemaParseList:
2319 * @ctxt: a schema validation context
2320 * @schema: the schema being built
2321 * @node: a subtree containing XML Schema informations
2322 *
2323 * parse a XML schema List definition
2324 * *WARNING* this interface is highly subject to change
2325 *
2326 * Returns -1 in case of error, 0 if the declaration is inproper and
2327 * 1 in case of success.
2328 */
2329static xmlSchemaTypePtr
2330xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002331 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002332{
2333 xmlSchemaTypePtr type, subtype;
2334 xmlNodePtr child = NULL;
2335 xmlChar name[30];
2336
2337 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2338 return (NULL);
2339
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002340 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002341 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002342 if (type == NULL)
2343 return (NULL);
2344 type->node = node;
2345 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002346 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002347 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002348 if ((type->ref != NULL) && (type->refNs == NULL))
2349 type->refNs = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00002350
2351 child = node->children;
2352 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002353 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2354 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002355 }
2356 subtype = NULL;
2357 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002358 subtype = (xmlSchemaTypePtr)
2359 xmlSchemaParseSimpleType(ctxt, schema, child);
2360 child = child->next;
2361 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002362 }
2363 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002364 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2365 "List %s has unexpected content\n", type->name,
2366 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002367 }
2368 return (type);
2369}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002370
Daniel Veillard4255d502002-04-16 15:50:10 +00002371/**
2372 * xmlSchemaParseSimpleType:
2373 * @ctxt: a schema validation context
2374 * @schema: the schema being built
2375 * @node: a subtree containing XML Schema informations
2376 *
2377 * parse a XML schema Simple Type definition
2378 * *WARNING* this interface is highly subject to change
2379 *
2380 * Returns -1 in case of error, 0 if the declaration is inproper and
2381 * 1 in case of success.
2382 */
2383static xmlSchemaTypePtr
2384xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2385 xmlNodePtr node)
2386{
2387 xmlSchemaTypePtr type, subtype;
2388 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002389 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002390
2391 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2392 return (NULL);
2393
2394
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002395 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002396 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002397 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002398
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002399 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2400 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2401 } else {
2402 const xmlChar *local, *ns;
2403
2404 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2405 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002406 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002407 if (type == NULL)
2408 return (NULL);
2409 type->node = node;
2410 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002411 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002412
2413 child = node->children;
2414 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2416 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002417 }
2418 subtype = NULL;
2419 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002420 subtype = (xmlSchemaTypePtr)
2421 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2422 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002423 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002424 subtype = (xmlSchemaTypePtr)
2425 xmlSchemaParseList(ctxt, schema, child);
2426 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002427 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002428 subtype = (xmlSchemaTypePtr)
2429 xmlSchemaParseUnion(ctxt, schema, child);
2430 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002431 }
2432 type->subtypes = subtype;
2433 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002434 xmlSchemaPErr2(ctxt, node, child,
2435 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2436 "SimpleType %s has unexpected content\n",
2437 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002438 }
2439
2440 return (type);
2441}
2442
2443
2444/**
2445 * xmlSchemaParseGroup:
2446 * @ctxt: a schema validation context
2447 * @schema: the schema being built
2448 * @node: a subtree containing XML Schema informations
2449 *
2450 * parse a XML schema Group definition
2451 * *WARNING* this interface is highly subject to change
2452 *
2453 * Returns -1 in case of error, 0 if the declaration is inproper and
2454 * 1 in case of success.
2455 */
2456static xmlSchemaTypePtr
2457xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002458 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002459{
2460 xmlSchemaTypePtr type, subtype;
2461 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002462 const xmlChar *name;
2463 const xmlChar *ref = NULL, *refNs = NULL;
2464 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002465
2466 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2467 return (NULL);
2468
2469
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002470 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002471 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002472
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002473 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2474 if (ref == NULL) {
2475 xmlSchemaPErr2(ctxt, node, child,
2476 XML_SCHEMAP_GROUP_NONAME_NOREF,
2477 "Group has no name nor ref\n", NULL, NULL);
2478 return (NULL);
2479 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002480 if (refNs == NULL)
2481 refNs = schema->targetNamespace;
2482 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2483 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002484 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002485 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002486 if (type == NULL)
2487 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002488
Daniel Veillard4255d502002-04-16 15:50:10 +00002489 type->node = node;
2490 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002491 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002492 type->ref = ref;
2493 type->refNs = refNs;
2494 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2495 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2496
2497 child = node->children;
2498 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002499 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2500 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002501 }
2502 subtype = NULL;
2503 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002504 subtype = (xmlSchemaTypePtr)
2505 xmlSchemaParseAll(ctxt, schema, child);
2506 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002507 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002508 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2509 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002510 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002511 subtype = (xmlSchemaTypePtr)
2512 xmlSchemaParseSequence(ctxt, schema, child);
2513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002514 }
2515 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002516 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002517 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002518 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2519 "Group %s has unexpected content\n", type->name,
2520 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002521 }
2522
2523 return (type);
2524}
2525
2526/**
2527 * xmlSchemaParseAll:
2528 * @ctxt: a schema validation context
2529 * @schema: the schema being built
2530 * @node: a subtree containing XML Schema informations
2531 *
2532 * parse a XML schema All definition
2533 * *WARNING* this interface is highly subject to change
2534 *
2535 * Returns -1 in case of error, 0 if the declaration is inproper and
2536 * 1 in case of success.
2537 */
2538static xmlSchemaTypePtr
2539xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002540 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002541{
2542 xmlSchemaTypePtr type, subtype, last = NULL;
2543 xmlNodePtr child = NULL;
2544 xmlChar name[30];
2545
2546 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2547 return (NULL);
2548
2549
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002550 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002551 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002552 if (type == NULL)
2553 return (NULL);
2554 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002555 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002556 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002557 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002558 if (type->minOccurs > 1)
2559 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2560 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002561 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002562 if (type->maxOccurs > 1)
2563 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2564 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002565
2566 child = node->children;
2567 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002568 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2569 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002570 }
2571 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002572 subtype = (xmlSchemaTypePtr)
2573 xmlSchemaParseElement(ctxt, schema, child, 0);
2574 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002575 if (subtype->minOccurs > 1)
2576 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2577 "invalid value for minOccurs (must be 0 or 1)\n",
2578 NULL, NULL);
2579 if (subtype->maxOccurs > 1)
2580 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2581 "invalid value for maxOccurs (must be 0 or 1)\n",
2582 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002583 if (last == NULL) {
2584 type->subtypes = subtype;
2585 last = subtype;
2586 } else {
2587 last->next = subtype;
2588 last = subtype;
2589 }
2590 last->next = NULL;
2591 }
2592 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002593 }
2594 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002595 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2596 "All %s has unexpected content\n", type->name,
2597 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002598 }
2599
2600 return (type);
2601}
2602
2603/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002604 * xmlSchemaImportSchema
2605 *
2606 * @ctxt: a schema validation context
2607 * @schemaLocation: an URI defining where to find the imported schema
2608 *
2609 * import a XML schema
2610 * *WARNING* this interface is highly subject to change
2611 *
2612 * Returns -1 in case of error and 1 in case of success.
2613 */
2614static xmlSchemaImportPtr
2615xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2616 const xmlChar *schemaLocation)
2617{
2618 xmlSchemaImportPtr import;
2619 xmlSchemaParserCtxtPtr newctxt;
2620
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002621 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002622 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002623 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002624 NULL);
2625 return (NULL);
2626 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002627 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2628 /* Keep the same dictionnary for parsing, really */
2629 xmlDictReference(ctxt->dict);
2630 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002631 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002632 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2633
Daniel Veillard1d913862003-11-21 00:28:39 +00002634 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2635 ctxt->userData);
2636
2637 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2638 if (import == NULL) {
2639 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2640 NULL);
2641 xmlSchemaFreeParserCtxt(newctxt);
2642 return (NULL);
2643 }
2644
2645 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002646 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002647 import->schema = xmlSchemaParse(newctxt);
2648
2649 if (import->schema == NULL) {
2650 /* FIXME use another error enum here ? */
2651 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2652 "failed to import schema at location %s\n",
2653 schemaLocation, NULL);
2654
2655 xmlSchemaFreeParserCtxt(newctxt);
2656 if (import->schemaLocation != NULL)
2657 xmlFree((xmlChar *)import->schemaLocation);
2658 xmlFree(import);
2659 return NULL;
2660 }
2661
2662 xmlSchemaFreeParserCtxt(newctxt);
2663 return import;
2664}
2665
2666
2667/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002668 * xmlSchemaParseImport:
2669 * @ctxt: a schema validation context
2670 * @schema: the schema being built
2671 * @node: a subtree containing XML Schema informations
2672 *
2673 * parse a XML schema Import definition
2674 * *WARNING* this interface is highly subject to change
2675 *
2676 * Returns -1 in case of error, 0 if the declaration is inproper and
2677 * 1 in case of success.
2678 */
2679static int
2680xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002681 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002682{
2683 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002684 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002685 const xmlChar *namespace;
2686 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002687 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002688 xmlURIPtr check;
2689
Daniel Veillard1d913862003-11-21 00:28:39 +00002690
Daniel Veillard5a872412002-05-22 06:40:27 +00002691 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2692 return (-1);
2693
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002694 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002695 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002696 check = xmlParseURI((const char *) namespace);
2697 if (check == NULL) {
2698 xmlSchemaPErr2(ctxt, node, child,
2699 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2700 "Import namespace attribute is not an URI: %s\n",
2701 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002702 return (-1);
2703 } else {
2704 xmlFreeURI(check);
2705 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002706 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002707 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002708 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002709 xmlChar *base = NULL;
2710 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002711 check = xmlParseURI((const char *) schemaLocation);
2712 if (check == NULL) {
2713 xmlSchemaPErr2(ctxt, node, child,
2714 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2715 "Import schemaLocation attribute is not an URI: %s\n",
2716 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002717 return (-1);
2718 } else {
2719 xmlFreeURI(check);
2720 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002721 base = xmlNodeGetBase(node->doc, node);
2722 if (base == NULL) {
2723 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2724 } else {
2725 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002726 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002727 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002728 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002729 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2730 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002731 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002732 }
2733 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002734 schema->schemasImports = xmlHashCreate(10);
2735 if (schema->schemasImports == NULL) {
2736 xmlSchemaPErr2(ctxt, node, child,
2737 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2738 "Internal: failed to build import table\n",
2739 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002740 return (-1);
2741 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002742 }
2743 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002744 import = xmlHashLookup(schema->schemasImports,
2745 XML_SCHEMAS_DEFAULT_NAMESPACE);
2746 if (import != NULL)
2747 previous = import->schemaLocation;
2748 else
2749 previous = NULL;
2750
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002751 if (schemaLocation != NULL) {
2752 if (previous != NULL) {
2753 if (!xmlStrEqual(schemaLocation, previous)) {
2754 xmlSchemaPErr2(ctxt, node, child,
2755 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2756 "Redefining import for default namespace with a different URI: %s\n",
2757 schemaLocation, NULL);
2758 }
2759 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002760 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2761 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002762 return (-1);
2763 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 xmlHashAddEntry(schema->schemasImports,
2765 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002766 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002767 }
2768 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002769 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002770 import = xmlHashLookup(schema->schemasImports, namespace);
2771 if (import != NULL)
2772 previous = import->schemaLocation;
2773 else
2774 previous = NULL;
2775
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002776 if (schemaLocation != NULL) {
2777 if (previous != NULL) {
2778 if (!xmlStrEqual(schemaLocation, previous)) {
2779 xmlSchemaPErr2(ctxt, node, child,
2780 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2781 "Redefining import for namespace %s with a different URI: %s\n",
2782 namespace, schemaLocation);
2783 }
2784 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002785 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2786 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002787 return (-1);
2788 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002789 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002790 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002791 }
2792 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002793 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002794
2795 child = node->children;
2796 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002797 /*
2798 * the annotations here are simply discarded ...
2799 */
2800 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002801 }
2802 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002803 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2804 "Import has unexpected content\n", NULL, NULL);
2805 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002806 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002807 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002808}
2809
2810/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002811 * xmlSchemaCleanupDoc:
2812 * @ctxt: a schema validation context
2813 * @node: the root of the document.
2814 *
2815 * removes unwanted nodes in a schemas document tree
2816 */
2817static void
2818xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
2819{
2820 xmlNodePtr delete, cur;
2821
2822 if ((ctxt == NULL) || (root == NULL)) return;
2823
2824 /*
2825 * Remove all the blank text nodes
2826 */
2827 delete = NULL;
2828 cur = root;
2829 while (cur != NULL) {
2830 if (delete != NULL) {
2831 xmlUnlinkNode(delete);
2832 xmlFreeNode(delete);
2833 delete = NULL;
2834 }
2835 if (cur->type == XML_TEXT_NODE) {
2836 if (IS_BLANK_NODE(cur)) {
2837 if (xmlNodeGetSpacePreserve(cur) != 1) {
2838 delete = cur;
2839 }
2840 }
2841 } else if ((cur->type != XML_ELEMENT_NODE) &&
2842 (cur->type != XML_CDATA_SECTION_NODE)) {
2843 delete = cur;
2844 goto skip_children;
2845 }
2846
2847 /*
2848 * Skip to next node
2849 */
2850 if (cur->children != NULL) {
2851 if ((cur->children->type != XML_ENTITY_DECL) &&
2852 (cur->children->type != XML_ENTITY_REF_NODE) &&
2853 (cur->children->type != XML_ENTITY_NODE)) {
2854 cur = cur->children;
2855 continue;
2856 }
2857 }
2858 skip_children:
2859 if (cur->next != NULL) {
2860 cur = cur->next;
2861 continue;
2862 }
2863
2864 do {
2865 cur = cur->parent;
2866 if (cur == NULL)
2867 break;
2868 if (cur == root) {
2869 cur = NULL;
2870 break;
2871 }
2872 if (cur->next != NULL) {
2873 cur = cur->next;
2874 break;
2875 }
2876 } while (cur != NULL);
2877 }
2878 if (delete != NULL) {
2879 xmlUnlinkNode(delete);
2880 xmlFreeNode(delete);
2881 delete = NULL;
2882 }
2883}
2884
2885/**
2886 * xmlSchemaParseSchemaTopLevel:
2887 * @ctxt: a schema validation context
2888 * @schema: the schemas
2889 * @nodes: the list of top level nodes
2890 *
2891 * Returns the internal XML Schema structure built from the resource or
2892 * NULL in case of error
2893 */
2894static void
2895xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
2896 xmlSchemaPtr schema, xmlNodePtr nodes)
2897{
2898 xmlNodePtr child;
2899 xmlSchemaAnnotPtr annot;
2900
2901 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
2902 return;
2903
2904 child = nodes;
2905 while ((IS_SCHEMA(child, "include")) ||
2906 (IS_SCHEMA(child, "import")) ||
2907 (IS_SCHEMA(child, "redefine")) ||
2908 (IS_SCHEMA(child, "annotation"))) {
2909 if (IS_SCHEMA(child, "annotation")) {
2910 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2911 if (schema->annot == NULL)
2912 schema->annot = annot;
2913 else
2914 xmlSchemaFreeAnnot(annot);
2915 } else if (IS_SCHEMA(child, "import")) {
2916 xmlSchemaParseImport(ctxt, schema, child);
2917 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002918 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002919 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002920 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002921 } else if (IS_SCHEMA(child, "redefine")) {
2922 TODO
2923 }
2924 child = child->next;
2925 }
2926 while (child != NULL) {
2927 if (IS_SCHEMA(child, "complexType")) {
2928 xmlSchemaParseComplexType(ctxt, schema, child);
2929 child = child->next;
2930 } else if (IS_SCHEMA(child, "simpleType")) {
2931 xmlSchemaParseSimpleType(ctxt, schema, child);
2932 child = child->next;
2933 } else if (IS_SCHEMA(child, "element")) {
2934 xmlSchemaParseElement(ctxt, schema, child, 1);
2935 child = child->next;
2936 } else if (IS_SCHEMA(child, "attribute")) {
2937 xmlSchemaParseAttribute(ctxt, schema, child);
2938 child = child->next;
2939 } else if (IS_SCHEMA(child, "attributeGroup")) {
2940 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2941 child = child->next;
2942 } else if (IS_SCHEMA(child, "group")) {
2943 xmlSchemaParseGroup(ctxt, schema, child);
2944 child = child->next;
2945 } else if (IS_SCHEMA(child, "notation")) {
2946 xmlSchemaParseNotation(ctxt, schema, child);
2947 child = child->next;
2948 } else {
2949 xmlSchemaPErr2(ctxt, NULL, child,
2950 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
2951 "Schemas: unexpected element %s here \n",
2952 child->name, NULL);
2953 child = child->next;
2954 }
2955 while (IS_SCHEMA(child, "annotation")) {
2956 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2957 if (schema->annot == NULL)
2958 schema->annot = annot;
2959 else
2960 xmlSchemaFreeAnnot(annot);
2961 child = child->next;
2962 }
2963 }
2964}
2965
2966/**
2967 * xmlSchemaParseInclude:
2968 * @ctxt: a schema validation context
2969 * @schema: the schema being built
2970 * @node: a subtree containing XML Schema informations
2971 *
2972 * parse a XML schema Include definition
2973 *
2974 * Returns -1 in case of error, 0 if the declaration is inproper and
2975 * 1 in case of success.
2976 */
2977static int
2978xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2979 xmlNodePtr node)
2980{
2981 xmlNodePtr child = NULL;
2982 const xmlChar *schemaLocation;
2983 xmlURIPtr check;
2984 xmlDocPtr doc;
2985 xmlNodePtr root;
2986 xmlSchemaIncludePtr include;
2987
2988
2989 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2990 return (-1);
2991
2992 /*
2993 * Preliminary step, extract the URI-Reference for the include and
2994 * make an URI from the base.
2995 */
2996 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
2997 if (schemaLocation != NULL) {
2998 xmlChar *base = NULL;
2999 xmlChar *URI = NULL;
3000 check = xmlParseURI((const char *) schemaLocation);
3001 if (check == NULL) {
3002 xmlSchemaPErr2(ctxt, node, child,
3003 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3004 "Include schemaLocation attribute is not an URI: %s\n",
3005 schemaLocation, NULL);
3006 return (-1);
3007 } else {
3008 xmlFreeURI(check);
3009 }
3010 base = xmlNodeGetBase(node->doc, node);
3011 if (base == NULL) {
3012 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3013 } else {
3014 URI = xmlBuildURI(schemaLocation, base);
3015 xmlFree(base);
3016 }
3017 if (URI != NULL) {
3018 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3019 xmlFree(URI);
3020 }
3021 } else {
3022 xmlSchemaPErr2(ctxt, node, child,
3023 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3024 "Include schemaLocation attribute missing\n",
3025 NULL, NULL);
3026 return (-1);
3027 }
3028
3029 child = node->children;
3030 while (IS_SCHEMA(child, "annotation")) {
3031 /*
3032 * the annotations here are simply discarded ...
3033 */
3034 child = child->next;
3035 }
3036 if (child != NULL) {
3037 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3038 "Include has unexpected content\n", NULL, NULL);
3039 return (-1);
3040 }
3041
3042 /*
3043 * First step is to parse the input document into an DOM/Infoset
3044 */
3045 doc = xmlReadFile((const char *) schemaLocation, NULL,
3046 SCHEMAS_PARSE_OPTIONS);
3047 if (doc == NULL) {
3048 xmlSchemaPErr(ctxt, NULL,
3049 XML_SCHEMAP_FAILED_LOAD,
3050 "xmlSchemaParse: could not load %s\n",
3051 ctxt->URL, NULL);
3052 return(-1);
3053 }
3054
3055 /*
3056 * Then extract the root of the schema
3057 */
3058 root = xmlDocGetRootElement(doc);
3059 if (root == NULL) {
3060 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3061 XML_SCHEMAP_NOROOT,
3062 "schemas %s has no root", schemaLocation, NULL);
3063 xmlFreeDoc(doc);
3064 return (-1);
3065 }
3066
3067 /*
3068 * Remove all the blank text nodes
3069 */
3070 xmlSchemaCleanupDoc(ctxt, root);
3071
3072 /*
3073 * Check the schemas top level element
3074 */
3075 if (!IS_SCHEMA(root, "schema")) {
3076 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3077 XML_SCHEMAP_NOT_SCHEMA,
3078 "File %s is not a schemas", schemaLocation, NULL);
3079 xmlFreeDoc(doc);
3080 return (-1);
3081 }
3082
3083 /*
3084 * register the include
3085 */
3086 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3087 if (include == NULL) {
3088 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3089 xmlFreeDoc(doc);
3090 return (-1);
3091 }
3092
3093 memset(include, 0, sizeof(xmlSchemaInclude));
3094 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3095 include->doc = doc;
3096 include->next = schema->includes;
3097 schema->includes = include;
3098
3099
3100 /*
3101 * parse the declarations in the included file like if they
3102 * were in the original file.
3103 */
3104 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3105
3106 return (1);
3107}
3108
3109/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003110 * xmlSchemaParseChoice:
3111 * @ctxt: a schema validation context
3112 * @schema: the schema being built
3113 * @node: a subtree containing XML Schema informations
3114 *
3115 * parse a XML schema Choice definition
3116 * *WARNING* this interface is highly subject to change
3117 *
3118 * Returns -1 in case of error, 0 if the declaration is inproper and
3119 * 1 in case of success.
3120 */
3121static xmlSchemaTypePtr
3122xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003123 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003124{
3125 xmlSchemaTypePtr type, subtype, last = NULL;
3126 xmlNodePtr child = NULL;
3127 xmlChar name[30];
3128
3129 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3130 return (NULL);
3131
3132
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003133 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003134 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003135 if (type == NULL)
3136 return (NULL);
3137 type->node = node;
3138 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003139 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003140 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3141 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3142
3143 child = node->children;
3144 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003145 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3146 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003147 }
3148 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003149 (IS_SCHEMA(child, "group")) ||
3150 (IS_SCHEMA(child, "any")) ||
3151 (IS_SCHEMA(child, "choice")) ||
3152 (IS_SCHEMA(child, "sequence"))) {
3153 subtype = NULL;
3154 if (IS_SCHEMA(child, "element")) {
3155 subtype = (xmlSchemaTypePtr)
3156 xmlSchemaParseElement(ctxt, schema, child, 0);
3157 } else if (IS_SCHEMA(child, "group")) {
3158 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3159 } else if (IS_SCHEMA(child, "any")) {
3160 subtype = xmlSchemaParseAny(ctxt, schema, child);
3161 } else if (IS_SCHEMA(child, "sequence")) {
3162 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3163 } else if (IS_SCHEMA(child, "choice")) {
3164 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3165 }
3166 if (subtype != NULL) {
3167 if (last == NULL) {
3168 type->subtypes = subtype;
3169 last = subtype;
3170 } else {
3171 last->next = subtype;
3172 last = subtype;
3173 }
3174 last->next = NULL;
3175 }
3176 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 }
3178 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003179 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3180 "Choice %s has unexpected content\n", type->name,
3181 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003182 }
3183
3184 return (type);
3185}
3186
3187/**
3188 * xmlSchemaParseSequence:
3189 * @ctxt: a schema validation context
3190 * @schema: the schema being built
3191 * @node: a subtree containing XML Schema informations
3192 *
3193 * parse a XML schema Sequence definition
3194 * *WARNING* this interface is highly subject to change
3195 *
3196 * Returns -1 in case of error, 0 if the declaration is inproper and
3197 * 1 in case of success.
3198 */
3199static xmlSchemaTypePtr
3200xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003201 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003202{
3203 xmlSchemaTypePtr type, subtype, last = NULL;
3204 xmlNodePtr child = NULL;
3205 xmlChar name[30];
3206
3207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3208 return (NULL);
3209
3210
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003212 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 if (type == NULL)
3214 return (NULL);
3215 type->node = node;
3216 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003217 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3219 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3220
3221 child = node->children;
3222 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003223 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003225 }
3226 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003227 (IS_SCHEMA(child, "group")) ||
3228 (IS_SCHEMA(child, "any")) ||
3229 (IS_SCHEMA(child, "choice")) ||
3230 (IS_SCHEMA(child, "sequence"))) {
3231 subtype = NULL;
3232 if (IS_SCHEMA(child, "element")) {
3233 subtype = (xmlSchemaTypePtr)
3234 xmlSchemaParseElement(ctxt, schema, child, 0);
3235 } else if (IS_SCHEMA(child, "group")) {
3236 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3237 } else if (IS_SCHEMA(child, "any")) {
3238 subtype = xmlSchemaParseAny(ctxt, schema, child);
3239 } else if (IS_SCHEMA(child, "choice")) {
3240 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3241 } else if (IS_SCHEMA(child, "sequence")) {
3242 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3243 }
3244 if (subtype != NULL) {
3245 if (last == NULL) {
3246 type->subtypes = subtype;
3247 last = subtype;
3248 } else {
3249 last->next = subtype;
3250 last = subtype;
3251 }
3252 last->next = NULL;
3253 }
3254 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003255 }
3256 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003257 xmlSchemaPErr2(ctxt, node, child,
3258 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3259 "Sequence %s has unexpected content\n", type->name,
3260 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003261 }
3262
3263 return (type);
3264}
3265
3266/**
3267 * xmlSchemaParseRestriction:
3268 * @ctxt: a schema validation context
3269 * @schema: the schema being built
3270 * @node: a subtree containing XML Schema informations
3271 * @simple: is that part of a simple type.
3272 *
3273 * parse a XML schema Restriction definition
3274 * *WARNING* this interface is highly subject to change
3275 *
3276 * Returns the type definition or NULL in case of error
3277 */
3278static xmlSchemaTypePtr
3279xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3280 xmlNodePtr node, int simple)
3281{
3282 xmlSchemaTypePtr type, subtype;
3283 xmlSchemaFacetPtr facet, lastfacet = NULL;
3284 xmlNodePtr child = NULL;
3285 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003286 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003287
3288 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3289 return (NULL);
3290
3291 oldcontainer = ctxt->container;
3292
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003293 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003294 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003295 if (type == NULL)
3296 return (NULL);
3297 type->node = node;
3298 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003299 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003300 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3301 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003302 xmlSchemaPErr2(ctxt, node, child,
3303 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3304 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003305 }
3306 ctxt->container = name;
3307
3308 child = node->children;
3309 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003310 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3311 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003312 }
3313 subtype = NULL;
3314
3315 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003316 subtype = (xmlSchemaTypePtr)
3317 xmlSchemaParseAll(ctxt, schema, child);
3318 child = child->next;
3319 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003320 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003321 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3322 child = child->next;
3323 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003324 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003325 subtype = (xmlSchemaTypePtr)
3326 xmlSchemaParseSequence(ctxt, schema, child);
3327 child = child->next;
3328 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003329 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003330 subtype = (xmlSchemaTypePtr)
3331 xmlSchemaParseGroup(ctxt, schema, child);
3332 child = child->next;
3333 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003334 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003335 if (IS_SCHEMA(child, "simpleType")) {
3336 subtype = (xmlSchemaTypePtr)
3337 xmlSchemaParseSimpleType(ctxt, schema, child);
3338 child = child->next;
3339 type->baseType = subtype;
3340 }
3341 /*
3342 * Facets
3343 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003344 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003345 (IS_SCHEMA(child, "minExclusive")) ||
3346 (IS_SCHEMA(child, "maxInclusive")) ||
3347 (IS_SCHEMA(child, "maxExclusive")) ||
3348 (IS_SCHEMA(child, "totalDigits")) ||
3349 (IS_SCHEMA(child, "fractionDigits")) ||
3350 (IS_SCHEMA(child, "pattern")) ||
3351 (IS_SCHEMA(child, "enumeration")) ||
3352 (IS_SCHEMA(child, "whiteSpace")) ||
3353 (IS_SCHEMA(child, "length")) ||
3354 (IS_SCHEMA(child, "maxLength")) ||
3355 (IS_SCHEMA(child, "minLength"))) {
3356 facet = xmlSchemaParseFacet(ctxt, schema, child);
3357 if (facet != NULL) {
3358 if (lastfacet == NULL) {
3359 type->facets = facet;
3360 lastfacet = facet;
3361 } else {
3362 lastfacet->next = facet;
3363 lastfacet = facet;
3364 }
3365 lastfacet->next = NULL;
3366 }
3367 child = child->next;
3368 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003369 }
3370 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3371 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003372 xmlSchemaPErr2(ctxt, node, child,
3373 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3374 "Restriction %s has unexpected content\n",
3375 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003376 }
3377 ctxt->container = oldcontainer;
3378 return (type);
3379}
3380
3381/**
3382 * xmlSchemaParseExtension:
3383 * @ctxt: a schema validation context
3384 * @schema: the schema being built
3385 * @node: a subtree containing XML Schema informations
3386 *
3387 * parse a XML schema Extension definition
3388 * *WARNING* this interface is highly subject to change
3389 *
3390 * Returns the type definition or NULL in case of error
3391 */
3392static xmlSchemaTypePtr
3393xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003394 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003395{
3396 xmlSchemaTypePtr type, subtype;
3397 xmlNodePtr child = NULL;
3398 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003399 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003400
3401 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3402 return (NULL);
3403
3404 oldcontainer = ctxt->container;
3405
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003406 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003407 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 if (type == NULL)
3409 return (NULL);
3410 type->node = node;
3411 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003412 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003413 ctxt->container = name;
3414
3415 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3416 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003417 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3418 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003419 }
3420 child = node->children;
3421 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003422 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3423 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003424 }
3425 subtype = NULL;
3426
3427 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003428 subtype = xmlSchemaParseAll(ctxt, schema, child);
3429 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003430 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003431 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3432 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003433 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003434 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3435 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003436 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003437 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3438 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003439 }
3440 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003441 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003442 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3443 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003444 xmlSchemaPErr2(ctxt, node, child,
3445 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3446 "Extension %s has unexpected content\n", type->name,
3447 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003448 }
3449 ctxt->container = oldcontainer;
3450 return (type);
3451}
3452
3453/**
3454 * xmlSchemaParseSimpleContent:
3455 * @ctxt: a schema validation context
3456 * @schema: the schema being built
3457 * @node: a subtree containing XML Schema informations
3458 *
3459 * parse a XML schema SimpleContent definition
3460 * *WARNING* this interface is highly subject to change
3461 *
3462 * Returns the type definition or NULL in case of error
3463 */
3464static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003465xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3466 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003467{
3468 xmlSchemaTypePtr type, subtype;
3469 xmlNodePtr child = NULL;
3470 xmlChar name[30];
3471
3472 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3473 return (NULL);
3474
3475
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003476 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003477 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003478 if (type == NULL)
3479 return (NULL);
3480 type->node = node;
3481 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003482 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003483
3484 child = node->children;
3485 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003486 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3487 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003488 }
3489 subtype = NULL;
3490 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003491 subtype = (xmlSchemaTypePtr)
3492 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3493 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003495 subtype = (xmlSchemaTypePtr)
3496 xmlSchemaParseExtension(ctxt, schema, child);
3497 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003498 }
3499 type->subtypes = subtype;
3500 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003501 xmlSchemaPErr2(ctxt, node, child,
3502 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3503 "SimpleContent %s has unexpected content\n",
3504 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003505 }
3506 return (type);
3507}
3508
3509/**
3510 * xmlSchemaParseComplexContent:
3511 * @ctxt: a schema validation context
3512 * @schema: the schema being built
3513 * @node: a subtree containing XML Schema informations
3514 *
3515 * parse a XML schema ComplexContent definition
3516 * *WARNING* this interface is highly subject to change
3517 *
3518 * Returns the type definition or NULL in case of error
3519 */
3520static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003521xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3522 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003523{
3524 xmlSchemaTypePtr type, subtype;
3525 xmlNodePtr child = NULL;
3526 xmlChar name[30];
3527
3528 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3529 return (NULL);
3530
3531
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003532 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003533 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003534 if (type == NULL)
3535 return (NULL);
3536 type->node = node;
3537 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003538 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003539
3540 child = node->children;
3541 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003542 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3543 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003544 }
3545 subtype = NULL;
3546 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003547 subtype = (xmlSchemaTypePtr)
3548 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3549 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003550 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003551 subtype = (xmlSchemaTypePtr)
3552 xmlSchemaParseExtension(ctxt, schema, child);
3553 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003554 }
3555 type->subtypes = subtype;
3556 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003557 xmlSchemaPErr2(ctxt, node, child,
3558 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3559 "ComplexContent %s has unexpected content\n",
3560 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003561 }
3562 return (type);
3563}
3564
3565/**
3566 * xmlSchemaParseComplexType:
3567 * @ctxt: a schema validation context
3568 * @schema: the schema being built
3569 * @node: a subtree containing XML Schema informations
3570 *
3571 * parse a XML schema Complex Type definition
3572 * *WARNING* this interface is highly subject to change
3573 *
3574 * Returns the type definition or NULL in case of error
3575 */
3576static xmlSchemaTypePtr
3577xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3578 xmlNodePtr node)
3579{
3580 xmlSchemaTypePtr type, subtype;
3581 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003582 const xmlChar *name;
3583 const xmlChar *oldcontainer;
Daniel Veillard1aefc862004-03-04 11:40:48 +00003584 const xmlChar *mixed;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003585 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003586
3587 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3588 return (NULL);
3589
3590 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003591 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003593
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003594 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3595 name = (const xmlChar *)buf;
3596 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3597 } else {
3598 const xmlChar *local, *ns;
3599
3600 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3601 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003603 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003604 return (NULL);
3605 }
Daniel Veillard1aefc862004-03-04 11:40:48 +00003606
3607 mixed = xmlSchemaGetProp(ctxt, node, "mixed");
3608 if (mixed != NULL)
3609 type->flags |= XML_SCHEMAS_TYPE_MIXED;
3610
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 type->node = node;
3612 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003613 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 ctxt->container = name;
3615
3616 child = node->children;
3617 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003618 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3619 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 }
3621 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003622 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3623 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003625 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3626 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003628 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003629
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003630 if (IS_SCHEMA(child, "all")) {
3631 subtype = xmlSchemaParseAll(ctxt, schema, child);
3632 child = child->next;
3633 } else if (IS_SCHEMA(child, "choice")) {
3634 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3635 child = child->next;
3636 } else if (IS_SCHEMA(child, "sequence")) {
3637 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3638 child = child->next;
3639 } else if (IS_SCHEMA(child, "group")) {
3640 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3641 child = child->next;
3642 }
3643 if (subtype != NULL)
3644 type->subtypes = subtype;
3645 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003646 }
3647 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 xmlSchemaPErr2(ctxt, node, child,
3649 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3650 "ComplexType %s has unexpected content\n",
3651 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003652 }
3653 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003654 return (type);
3655}
3656
Daniel Veillard4255d502002-04-16 15:50:10 +00003657/**
3658 * xmlSchemaParseSchema:
3659 * @ctxt: a schema validation context
3660 * @node: a subtree containing XML Schema informations
3661 *
3662 * parse a XML schema definition from a node set
3663 * *WARNING* this interface is highly subject to change
3664 *
3665 * Returns the internal XML Schema structure built from the resource or
3666 * NULL in case of error
3667 */
3668static xmlSchemaPtr
3669xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3670{
3671 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003672 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003673 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003674 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003675
3676 if ((ctxt == NULL) || (node == NULL))
3677 return (NULL);
3678
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003679 nberrors = ctxt->nberrors;
3680 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003681 if (IS_SCHEMA(node, "schema")) {
3682 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003683 if (schema == NULL)
3684 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003685 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3686 if (val != NULL) {
3687 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3688 } else {
3689 schema->targetNamespace = NULL;
3690 }
3691 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3692 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3693 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003694 if (val != NULL) {
3695 if (xmlStrEqual(val, BAD_CAST "qualified"))
3696 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3697 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3698 xmlSchemaPErr2(ctxt, node, child,
3699 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3700 "Invalid value %s for elementFormDefault\n",
3701 val, NULL);
3702 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003703 } else {
3704 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3705 }
3706 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003707 if (val != NULL) {
3708 if (xmlStrEqual(val, BAD_CAST "qualified"))
3709 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3710 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3711 xmlSchemaPErr2(ctxt, node, child,
3712 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3713 "Invalid value %s for attributeFormDefault\n",
3714 val, NULL);
3715 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003716 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003717
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003718 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
3719 } else {
3720 xmlDocPtr doc;
3721
3722 doc = node->doc;
3723
3724 if ((doc != NULL) && (doc->URL != NULL)) {
3725 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3726 XML_SCHEMAP_NOT_SCHEMA,
3727 "File %s is not a schemas", doc->URL, NULL);
3728 } else {
3729 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3730 XML_SCHEMAP_NOT_SCHEMA,
3731 "File is not a schemas", NULL, NULL);
3732 }
3733 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003734 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003735 if (ctxt->nberrors != 0) {
3736 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003737 xmlSchemaFree(schema);
3738 schema = NULL;
3739 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003740 }
3741 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003742#ifdef DEBUG
3743 if (schema == NULL)
3744 xmlGenericError(xmlGenericErrorContext,
3745 "xmlSchemaParse() failed\n");
3746#endif
3747
3748 return (schema);
3749}
3750
3751/************************************************************************
3752 * *
3753 * Validating using Schemas *
3754 * *
3755 ************************************************************************/
3756
3757/************************************************************************
3758 * *
3759 * Reading/Writing Schemas *
3760 * *
3761 ************************************************************************/
3762
3763/**
3764 * xmlSchemaNewParserCtxt:
3765 * @URL: the location of the schema
3766 *
3767 * Create an XML Schemas parse context for that file/resource expected
3768 * to contain an XML Schemas file.
3769 *
3770 * Returns the parser context or NULL in case of error
3771 */
3772xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003773xmlSchemaNewParserCtxt(const char *URL)
3774{
Daniel Veillard4255d502002-04-16 15:50:10 +00003775 xmlSchemaParserCtxtPtr ret;
3776
3777 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003778 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003779
3780 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3781 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003782 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3783 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 return (NULL);
3785 }
3786 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003787 ret->dict = xmlDictCreate();
3788 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003789 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003790 return (ret);
3791}
3792
3793/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003794 * xmlSchemaNewMemParserCtxt:
3795 * @buffer: a pointer to a char array containing the schemas
3796 * @size: the size of the array
3797 *
3798 * Create an XML Schemas parse context for that memory buffer expected
3799 * to contain an XML Schemas file.
3800 *
3801 * Returns the parser context or NULL in case of error
3802 */
3803xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003804xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3805{
Daniel Veillard6045c902002-10-09 21:13:59 +00003806 xmlSchemaParserCtxtPtr ret;
3807
3808 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003809 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003810
3811 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3812 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003813 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3814 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003815 return (NULL);
3816 }
3817 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3818 ret->buffer = buffer;
3819 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003820 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00003821 return (ret);
3822}
3823
3824/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003825 * xmlSchemaNewDocParserCtxt:
3826 * @doc: a preparsed document tree
3827 *
3828 * Create an XML Schemas parse context for that document.
3829 * NB. The document may be modified during the parsing process.
3830 *
3831 * Returns the parser context or NULL in case of error
3832 */
3833xmlSchemaParserCtxtPtr
3834xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3835{
3836 xmlSchemaParserCtxtPtr ret;
3837
3838 if (doc == NULL)
3839 return (NULL);
3840
3841 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3842 if (ret == NULL) {
3843 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3844 NULL);
3845 return (NULL);
3846 }
3847 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3848 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003849 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00003850 /* The application has responsibility for the document */
3851 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00003852
3853 return (ret);
3854}
3855
3856/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003857 * xmlSchemaFreeParserCtxt:
3858 * @ctxt: the schema parser context
3859 *
3860 * Free the resources associated to the schema parser context
3861 */
3862void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003863xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3864{
Daniel Veillard4255d502002-04-16 15:50:10 +00003865 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003866 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00003867 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003868 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003869 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003870 xmlFree(ctxt);
3871}
3872
3873/************************************************************************
3874 * *
3875 * Building the content models *
3876 * *
3877 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003878
Daniel Veillard4255d502002-04-16 15:50:10 +00003879/**
3880 * xmlSchemaBuildAContentModel:
3881 * @type: the schema type definition
3882 * @ctxt: the schema parser context
3883 * @name: the element name whose content is being built
3884 *
3885 * Generate the automata sequence needed for that type
3886 */
3887static void
3888xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003889 xmlSchemaParserCtxtPtr ctxt,
3890 const xmlChar * name)
3891{
Daniel Veillard4255d502002-04-16 15:50:10 +00003892 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 xmlGenericError(xmlGenericErrorContext,
3894 "Found unexpected type = NULL in %s content model\n",
3895 name);
3896 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003897 }
3898 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003899 case XML_SCHEMA_TYPE_ANY:
3900 /* TODO : handle the namespace too */
3901 /* TODO : make that a specific transition type */
3902 TODO ctxt->state =
3903 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3904 BAD_CAST "*", NULL);
3905 break;
3906 case XML_SCHEMA_TYPE_ELEMENT:{
3907 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003908
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003909 /* TODO : handle the namespace too */
3910 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003911
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003912 if (elem->maxOccurs >= UNBOUNDED) {
3913 if (elem->minOccurs > 1) {
3914 xmlAutomataStatePtr tmp;
3915 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003916
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003917 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3918 oldstate,
3919 NULL);
3920 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003921
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003922 counter = xmlAutomataNewCounter(ctxt->am,
3923 elem->minOccurs -
3924 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003925
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003926 if (elem->refDecl != NULL) {
3927 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3928 elem->refDecl,
3929 ctxt,
3930 elem->refDecl->
3931 name);
3932 } else {
3933 ctxt->state =
3934 xmlAutomataNewTransition(ctxt->am,
3935 ctxt->state, NULL,
3936 elem->name, type);
3937 }
3938 tmp = ctxt->state;
3939 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3940 counter);
3941 ctxt->state =
3942 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3943 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003944
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003945 } else {
3946 if (elem->refDecl != NULL) {
3947 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3948 elem->refDecl,
3949 ctxt,
3950 elem->refDecl->
3951 name);
3952 } else {
3953 ctxt->state =
3954 xmlAutomataNewTransition(ctxt->am,
3955 ctxt->state, NULL,
3956 elem->name, type);
3957 }
3958 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3959 oldstate);
3960 if (elem->minOccurs == 0) {
3961 /* basically an elem* */
3962 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3963 ctxt->state);
3964 }
3965 }
3966 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3967 xmlAutomataStatePtr tmp;
3968 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003969
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003970 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3971 oldstate, NULL);
3972 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003973
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003974 counter = xmlAutomataNewCounter(ctxt->am,
3975 elem->minOccurs - 1,
3976 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003977
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003978 if (elem->refDecl != NULL) {
3979 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3980 elem->refDecl, ctxt,
3981 elem->refDecl->name);
3982 } else {
3983 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3984 ctxt->state,
3985 NULL,
3986 elem->name,
3987 type);
3988 }
3989 tmp = ctxt->state;
3990 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3991 counter);
3992 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3993 NULL,
3994 counter);
3995 if (elem->minOccurs == 0) {
3996 /* basically an elem? */
3997 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3998 ctxt->state);
3999 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00004000
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004001 } else {
4002 if (elem->refDecl != NULL) {
4003 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
4004 elem->refDecl, ctxt,
4005 elem->refDecl->name);
4006 } else {
4007 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4008 ctxt->state,
4009 NULL,
4010 elem->name,
4011 type);
4012 }
4013 if (elem->minOccurs == 0) {
4014 /* basically an elem? */
4015 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4016 ctxt->state);
4017 }
4018 }
4019 break;
4020 }
4021 case XML_SCHEMA_TYPE_SEQUENCE:{
4022 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004023
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004024 /*
4025 * If max and min occurances are default (1) then
4026 * simply iterate over the subtypes
4027 */
4028 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4029 subtypes = type->subtypes;
4030 while (subtypes != NULL) {
4031 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4032 subtypes = subtypes->next;
4033 }
4034 } else {
4035 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004036
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004037 if (type->maxOccurs >= UNBOUNDED) {
4038 if (type->minOccurs > 1) {
4039 xmlAutomataStatePtr tmp;
4040 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004041
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004042 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4043 oldstate,
4044 NULL);
4045 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004046
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004047 counter = xmlAutomataNewCounter(ctxt->am,
4048 type->
4049 minOccurs - 1,
4050 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004051
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004052 subtypes = type->subtypes;
4053 while (subtypes != NULL) {
4054 xmlSchemaBuildAContentModel(subtypes, ctxt,
4055 name);
4056 subtypes = subtypes->next;
4057 }
4058 tmp = ctxt->state;
4059 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4060 oldstate, counter);
4061 ctxt->state =
4062 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4063 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004064
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004065 } else {
4066 subtypes = type->subtypes;
4067 while (subtypes != NULL) {
4068 xmlSchemaBuildAContentModel(subtypes, ctxt,
4069 name);
4070 subtypes = subtypes->next;
4071 }
4072 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4073 oldstate);
4074 if (type->minOccurs == 0) {
4075 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4076 ctxt->state);
4077 }
4078 }
4079 } else if ((type->maxOccurs > 1)
4080 || (type->minOccurs > 1)) {
4081 xmlAutomataStatePtr tmp;
4082 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004083
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004084 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4085 oldstate,
4086 NULL);
4087 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004088
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004089 counter = xmlAutomataNewCounter(ctxt->am,
4090 type->minOccurs -
4091 1,
4092 type->maxOccurs -
4093 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004094
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004095 subtypes = type->subtypes;
4096 while (subtypes != NULL) {
4097 xmlSchemaBuildAContentModel(subtypes, ctxt,
4098 name);
4099 subtypes = subtypes->next;
4100 }
4101 tmp = ctxt->state;
4102 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4103 counter);
4104 ctxt->state =
4105 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4106 counter);
4107 if (type->minOccurs == 0) {
4108 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4109 ctxt->state);
4110 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004111
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004112 } else {
4113 subtypes = type->subtypes;
4114 while (subtypes != NULL) {
4115 xmlSchemaBuildAContentModel(subtypes, ctxt,
4116 name);
4117 subtypes = subtypes->next;
4118 }
4119 if (type->minOccurs == 0) {
4120 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4121 ctxt->state);
4122 }
4123 }
4124 }
4125 break;
4126 }
4127 case XML_SCHEMA_TYPE_CHOICE:{
4128 xmlSchemaTypePtr subtypes;
4129 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004130
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004131 start = ctxt->state;
4132 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004133
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004134 /*
4135 * iterate over the subtypes and remerge the end with an
4136 * epsilon transition
4137 */
4138 if (type->maxOccurs == 1) {
4139 subtypes = type->subtypes;
4140 while (subtypes != NULL) {
4141 ctxt->state = start;
4142 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4143 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4144 subtypes = subtypes->next;
4145 }
4146 } else {
4147 int counter;
4148 xmlAutomataStatePtr hop;
4149 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4150 UNBOUNDED : type->maxOccurs - 1;
4151 int minOccurs =
4152 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004153
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004154 /*
4155 * use a counter to keep track of the number of transtions
4156 * which went through the choice.
4157 */
4158 counter =
4159 xmlAutomataNewCounter(ctxt->am, minOccurs,
4160 maxOccurs);
4161 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004162
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004163 subtypes = type->subtypes;
4164 while (subtypes != NULL) {
4165 ctxt->state = start;
4166 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4167 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4168 subtypes = subtypes->next;
4169 }
4170 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4171 counter);
4172 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4173 counter);
4174 }
4175 if (type->minOccurs == 0) {
4176 xmlAutomataNewEpsilon(ctxt->am, start, end);
4177 }
4178 ctxt->state = end;
4179 break;
4180 }
4181 case XML_SCHEMA_TYPE_ALL:{
4182 xmlAutomataStatePtr start;
4183 xmlSchemaTypePtr subtypes;
4184 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4185 int lax;
4186
4187 subtypes = type->subtypes;
4188 if (subtypes == NULL)
4189 break;
4190 start = ctxt->state;
4191 while (subtypes != NULL) {
4192 ctxt->state = start;
4193 elem = (xmlSchemaElementPtr) subtypes;
4194
4195 /* TODO : handle the namespace too */
4196 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4197 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4198 ctxt->state, elem->name, 1,
4199 1, subtypes);
4200 } else {
4201 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4202 ctxt->state, elem->name,
4203 elem->minOccurs,
4204 elem->maxOccurs,
4205 subtypes);
4206 }
4207 subtypes = subtypes->next;
4208 }
4209 lax = type->minOccurs == 0;
4210 ctxt->state =
4211 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4212 lax);
4213 break;
4214 }
4215 case XML_SCHEMA_TYPE_RESTRICTION:
4216 if (type->subtypes != NULL)
4217 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4218 break;
4219 case XML_SCHEMA_TYPE_EXTENSION:
4220 if (type->baseType != NULL) {
4221 xmlSchemaTypePtr subtypes;
4222
4223 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4224 subtypes = type->subtypes;
4225 while (subtypes != NULL) {
4226 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4227 subtypes = subtypes->next;
4228 }
4229 } else if (type->subtypes != NULL)
4230 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4231 break;
4232 case XML_SCHEMA_TYPE_GROUP:
4233 if (type->subtypes == NULL) {
4234 }
4235 case XML_SCHEMA_TYPE_COMPLEX:
4236 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4237 if (type->subtypes != NULL)
4238 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4239 break;
4240 default:
4241 xmlGenericError(xmlGenericErrorContext,
4242 "Found unexpected type %d in %s content model\n",
4243 type->type, name);
4244 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004245 }
4246}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004247
Daniel Veillard4255d502002-04-16 15:50:10 +00004248/**
4249 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004250 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004251 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004252 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004253 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004254 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004255 */
4256static void
4257xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004258 xmlSchemaParserCtxtPtr ctxt,
4259 const xmlChar * name)
4260{
Daniel Veillard4255d502002-04-16 15:50:10 +00004261 xmlAutomataStatePtr start;
4262
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004265 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004266 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4267 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004268 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004270 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004271 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4272 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004273 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004274
4275#ifdef DEBUG_CONTENT
4276 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004277 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004278#endif
4279
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 ctxt->am = xmlNewAutomata();
4281 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004282 xmlGenericError(xmlGenericErrorContext,
4283 "Cannot create automata for elem %s\n", name);
4284 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004285 }
4286 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4287 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4288 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004289 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004290 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004291 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4292 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004293 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4295 "Content model of %s is not determinist:\n", name,
4296 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004297 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004298#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004299 xmlGenericError(xmlGenericErrorContext,
4300 "Content model of %s:\n", name);
4301 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004302#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004303 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004304 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004305 xmlFreeAutomata(ctxt->am);
4306 ctxt->am = NULL;
4307}
4308
4309/**
4310 * xmlSchemaRefFixupCallback:
4311 * @elem: the schema element context
4312 * @ctxt: the schema parser context
4313 *
4314 * Free the resources associated to the schema parser context
4315 */
4316static void
4317xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004318 xmlSchemaParserCtxtPtr ctxt,
4319 const xmlChar * name,
4320 const xmlChar * context ATTRIBUTE_UNUSED,
4321 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004322{
4323 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004324 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004325 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004326 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004327
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004328 if (elem->subtypes != NULL) {
4329 xmlSchemaPErr(ctxt, elem->node,
4330 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4331 "Schemas: element %s have both ref and subtype\n",
4332 name, NULL);
4333 return;
4334 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004335 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004336
4337 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004338 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4339 "Schemas: element %s ref to %s not found\n",
4340 name, elem->ref);
4341 return;
4342 }
4343 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004345 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004346
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004347 if (elem->subtypes != NULL) {
4348 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4349 "Schemas: element %s have both type and subtype\n",
4350 name, NULL);
4351 return;
4352 }
4353 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4354 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004355
4356 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004357 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4358 "Schemas: element %s type %s not found\n", name,
4359 elem->namedType);
4360 return;
4361 }
4362 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004363 }
4364}
4365
4366/**
4367 * xmlSchemaTypeFixup:
4368 * @typeDecl: the schema type definition
4369 * @ctxt: the schema parser context
4370 *
4371 * Fixes the content model of the type.
4372 */
4373static void
4374xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004375 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004376{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004377 if (typeDecl == NULL)
4378 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004379 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004380 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004382 switch (typeDecl->type) {
4383 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4384 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4385 if (typeDecl->subtypes != NULL)
4386 typeDecl->contentType =
4387 typeDecl->subtypes->contentType;
4388 break;
4389 }
4390 case XML_SCHEMA_TYPE_RESTRICTION:{
4391 if (typeDecl->subtypes != NULL)
4392 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004393
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 if (typeDecl->base != NULL) {
4395 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004396
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004397 baseType =
4398 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4399 typeDecl->baseNs);
4400 if (baseType == NULL) {
4401 xmlSchemaPErr(ctxt, typeDecl->node,
4402 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 name, typeDecl->base);
4405 }
4406 typeDecl->baseType = baseType;
4407 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004408 if (typeDecl->subtypes == NULL)
4409 if (typeDecl->baseType != NULL)
4410 typeDecl->contentType =
4411 typeDecl->baseType->contentType;
4412 else
4413 /* 1.1.1 */
4414 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004415 else if ((typeDecl->subtypes->subtypes == NULL) &&
4416 ((typeDecl->subtypes->type ==
4417 XML_SCHEMA_TYPE_ALL)
4418 || (typeDecl->subtypes->type ==
4419 XML_SCHEMA_TYPE_SEQUENCE)))
4420 /* 1.1.2 */
4421 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4422 else if ((typeDecl->subtypes->type ==
4423 XML_SCHEMA_TYPE_CHOICE)
4424 && (typeDecl->subtypes->subtypes == NULL))
4425 /* 1.1.3 */
4426 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4427 else {
4428 /* 1.2 and 2.X are applied at the other layer */
4429 typeDecl->contentType =
4430 XML_SCHEMA_CONTENT_ELEMENTS;
4431 }
4432 break;
4433 }
4434 case XML_SCHEMA_TYPE_EXTENSION:{
4435 xmlSchemaContentType explicitContentType;
4436 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004437
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004438 if (typeDecl->base != NULL) {
4439 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004440
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 baseType =
4442 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4443 typeDecl->baseNs);
4444 if (baseType == NULL) {
4445 xmlSchemaPErr(ctxt, typeDecl->node,
4446 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004447 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004448 name, typeDecl->base);
4449 }
4450 typeDecl->baseType = baseType;
4451 }
4452 if (typeDecl->subtypes != NULL)
4453 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004454
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004455 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4456 if (typeDecl->subtypes == NULL)
4457 /* 1.1.1 */
4458 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4459 else if ((typeDecl->subtypes->subtypes == NULL) &&
4460 ((typeDecl->subtypes->type ==
4461 XML_SCHEMA_TYPE_ALL)
4462 || (typeDecl->subtypes->type ==
4463 XML_SCHEMA_TYPE_SEQUENCE)))
4464 /* 1.1.2 */
4465 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4466 else if ((typeDecl->subtypes->type ==
4467 XML_SCHEMA_TYPE_CHOICE)
4468 && (typeDecl->subtypes->subtypes == NULL))
4469 /* 1.1.3 */
4470 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004471
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004472 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4473 typeDecl->baseNs);
4474 if (base == NULL) {
4475 xmlSchemaPErr(ctxt, typeDecl->node,
4476 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4477 "Schemas: base type %s of type %s not found\n",
4478 typeDecl->base, name);
4479 return;
4480 }
4481 xmlSchemaTypeFixup(base, ctxt, NULL);
4482 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4483 /* 2.1 */
4484 typeDecl->contentType = base->contentType;
4485 } else if (base->contentType ==
4486 XML_SCHEMA_CONTENT_EMPTY) {
4487 /* 2.2 imbitable ! */
4488 typeDecl->contentType =
4489 XML_SCHEMA_CONTENT_ELEMENTS;
4490 } else {
4491 /* 2.3 imbitable pareil ! */
4492 typeDecl->contentType =
4493 XML_SCHEMA_CONTENT_ELEMENTS;
4494 }
4495 break;
4496 }
4497 case XML_SCHEMA_TYPE_COMPLEX:{
4498 if (typeDecl->subtypes == NULL) {
4499 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004500
4501 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4502 typeDecl->contentType =
4503 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004504 } else {
4505 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4506 typeDecl->contentType =
4507 XML_SCHEMA_CONTENT_MIXED;
4508 else {
4509 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4510 NULL);
4511 if (typeDecl->subtypes != NULL)
4512 typeDecl->contentType =
4513 typeDecl->subtypes->contentType;
4514 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004515 if (typeDecl->attributes == NULL)
4516 typeDecl->attributes =
4517 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004518 }
4519 break;
4520 }
4521 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4522 if (typeDecl->subtypes == NULL) {
4523 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004524 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4525 typeDecl->contentType =
4526 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004527 } else {
4528 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4529 typeDecl->contentType =
4530 XML_SCHEMA_CONTENT_MIXED;
4531 else {
4532 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4533 NULL);
4534 if (typeDecl->subtypes != NULL)
4535 typeDecl->contentType =
4536 typeDecl->subtypes->contentType;
4537 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004538 if (typeDecl->attributes == NULL)
4539 typeDecl->attributes =
4540 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004541 }
4542 break;
4543 }
4544 case XML_SCHEMA_TYPE_SEQUENCE:
4545 case XML_SCHEMA_TYPE_GROUP:
4546 case XML_SCHEMA_TYPE_ALL:
4547 case XML_SCHEMA_TYPE_CHOICE:
4548 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4549 break;
4550 case XML_SCHEMA_TYPE_BASIC:
4551 case XML_SCHEMA_TYPE_ANY:
4552 case XML_SCHEMA_TYPE_FACET:
4553 case XML_SCHEMA_TYPE_SIMPLE:
4554 case XML_SCHEMA_TYPE_UR:
4555 case XML_SCHEMA_TYPE_ELEMENT:
4556 case XML_SCHEMA_TYPE_ATTRIBUTE:
4557 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4558 case XML_SCHEMA_TYPE_NOTATION:
4559 case XML_SCHEMA_TYPE_LIST:
4560 case XML_SCHEMA_TYPE_UNION:
4561 case XML_SCHEMA_FACET_MININCLUSIVE:
4562 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4563 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4564 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4565 case XML_SCHEMA_FACET_TOTALDIGITS:
4566 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4567 case XML_SCHEMA_FACET_PATTERN:
4568 case XML_SCHEMA_FACET_ENUMERATION:
4569 case XML_SCHEMA_FACET_WHITESPACE:
4570 case XML_SCHEMA_FACET_LENGTH:
4571 case XML_SCHEMA_FACET_MAXLENGTH:
4572 case XML_SCHEMA_FACET_MINLENGTH:
4573 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004574 if (typeDecl->subtypes != NULL)
4575 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004576 break;
4577 }
4578 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004579#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004580 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004581 xmlGenericError(xmlGenericErrorContext,
4582 "Type of %s : %s:%d :", name,
4583 typeDecl->node->doc->URL,
4584 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004585 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004586 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004587 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004588 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004589 case XML_SCHEMA_CONTENT_SIMPLE:
4590 xmlGenericError(xmlGenericErrorContext, "simple\n");
4591 break;
4592 case XML_SCHEMA_CONTENT_ELEMENTS:
4593 xmlGenericError(xmlGenericErrorContext, "elements\n");
4594 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004595 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004596 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4597 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004598 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004599 xmlGenericError(xmlGenericErrorContext, "empty\n");
4600 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004601 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004602 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4603 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004604 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004605 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4606 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004607 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004608 xmlGenericError(xmlGenericErrorContext, "basic\n");
4609 break;
4610 default:
4611 xmlGenericError(xmlGenericErrorContext,
4612 "not registered !!!\n");
4613 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004614 }
4615#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004616}
4617
4618/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004619 * xmlSchemaCheckFacet:
4620 * @facet: the facet
4621 * @typeDecl: the schema type definition
4622 * @ctxt: the schema parser context or NULL
4623 * @name: name of the type
4624 *
4625 * Checks the default values types, especially for facets
4626 *
4627 * Returns 0 if okay or -1 in cae of error
4628 */
4629int
4630xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631 xmlSchemaTypePtr typeDecl,
4632 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004633{
4634 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4635 int ret = 0;
4636
4637 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004638 nonNegativeIntegerType =
4639 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4640 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004641 }
4642 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004643 case XML_SCHEMA_FACET_MININCLUSIVE:
4644 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4645 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4646 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4647 /*
4648 * Okay we need to validate the value
4649 * at that point.
4650 */
4651 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004652
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004653 vctxt = xmlSchemaNewValidCtxt(NULL);
4654 if (vctxt == NULL)
4655 break;
4656 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4657 facet->value);
4658 facet->val = vctxt->value;
4659 vctxt->value = NULL;
4660 if (facet->val == NULL) {
4661 /* error code */
4662 if (ctxt != NULL) {
4663 xmlSchemaPErr(ctxt, facet->node,
4664 XML_SCHEMAP_INVALID_FACET,
4665 "Schemas: type %s facet value %s invalid\n",
4666 name, facet->value);
4667 }
4668 ret = -1;
4669 }
4670 xmlSchemaFreeValidCtxt(vctxt);
4671 break;
4672 }
4673 case XML_SCHEMA_FACET_ENUMERATION:{
4674 /*
4675 * Okay we need to validate the value
4676 * at that point.
4677 */
4678 xmlSchemaValidCtxtPtr vctxt;
4679 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004680
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004681 vctxt = xmlSchemaNewValidCtxt(NULL);
4682 if (vctxt == NULL)
4683 break;
4684 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4685 facet->value);
4686 if (tmp != 0) {
4687 if (ctxt != NULL) {
4688 xmlSchemaPErr(ctxt, facet->node,
4689 XML_SCHEMAP_INVALID_ENUM,
4690 "Schemas: type %s enumeration value %s invalid\n",
4691 name, facet->value);
4692 }
4693 ret = -1;
4694 }
4695 xmlSchemaFreeValidCtxt(vctxt);
4696 break;
4697 }
4698 case XML_SCHEMA_FACET_PATTERN:
4699 facet->regexp = xmlRegexpCompile(facet->value);
4700 if (facet->regexp == NULL) {
4701 xmlSchemaPErr(ctxt, typeDecl->node,
4702 XML_SCHEMAP_REGEXP_INVALID,
4703 "Schemas: type %s facet regexp %s invalid\n",
4704 name, facet->value);
4705 ret = -1;
4706 }
4707 break;
4708 case XML_SCHEMA_FACET_TOTALDIGITS:
4709 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4710 case XML_SCHEMA_FACET_LENGTH:
4711 case XML_SCHEMA_FACET_MAXLENGTH:
4712 case XML_SCHEMA_FACET_MINLENGTH:{
4713 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004714
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004715 tmp =
4716 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4717 facet->value,
4718 &facet->val);
4719 if (tmp != 0) {
4720 /* error code */
4721 if (ctxt != NULL) {
4722 xmlSchemaPErr(ctxt, facet->node,
4723 XML_SCHEMAP_INVALID_FACET_VALUE,
4724 "Schemas: type %s facet value %s invalid\n",
4725 name, facet->value);
4726 }
4727 ret = -1;
4728 }
4729 break;
4730 }
4731 case XML_SCHEMA_FACET_WHITESPACE:{
4732 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4733 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4734 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4735 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4736 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4737 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4738 } else {
4739 if (ctxt != NULL) {
4740 xmlSchemaPErr(ctxt, facet->node,
4741 XML_SCHEMAP_INVALID_WHITE_SPACE,
4742 "Schemas: type %s whiteSpace value %s invalid\n",
4743 name, facet->value);
4744 }
4745 ret = -1;
4746 }
4747 }
4748 default:
4749 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004750 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004751 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004752}
4753
4754/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004755 * xmlSchemaCheckDefaults:
4756 * @typeDecl: the schema type definition
4757 * @ctxt: the schema parser context
4758 *
4759 * Checks the default values types, especially for facets
4760 */
4761static void
4762xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004763 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004764{
Daniel Veillard4255d502002-04-16 15:50:10 +00004765 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004766 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004767 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004768 if (typeDecl->facets != NULL) {
4769 xmlSchemaFacetPtr facet = typeDecl->facets;
4770
4771 while (facet != NULL) {
4772 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4773 facet = facet->next;
4774 }
4775 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004776 }
4777}
4778
4779/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004780 * xmlSchemaAttrGrpFixup:
4781 * @attrgrpDecl: the schema attribute definition
4782 * @ctxt: the schema parser context
4783 * @name: the attribute name
4784 *
4785 * Fixes finish doing the computations on the attributes definitions
4786 */
4787static void
4788xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004790{
4791 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004792 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004793 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004794 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004795 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004796 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004797
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004798 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4799 attrgrpDecl->refNs);
4800 if (ref == NULL) {
4801 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4802 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4803 "Schemas: attribute group %s reference %s not found\n",
4804 name, attrgrpDecl->ref);
4805 return;
4806 }
4807 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4808 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004809 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004810 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4811 "Schemas: attribute %s has no attributes nor reference\n",
4812 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004813 }
4814}
4815
4816/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004817 * xmlSchemaAttrFixup:
4818 * @attrDecl: the schema attribute definition
4819 * @ctxt: the schema parser context
4820 * @name: the attribute name
4821 *
4822 * Fixes finish doing the computations on the attributes definitions
4823 */
4824static void
4825xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004826 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004827{
4828 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004829 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004830 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004832 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004833 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004834
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004835 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4836 attrDecl->typeNs);
4837 if (type == NULL) {
4838 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4839 "Schemas: attribute %s type %s not found\n",
4840 name, attrDecl->typeName);
4841 }
4842 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004843 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004844 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004845
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004846 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4847 attrDecl->refNs);
4848 if (ref == NULL) {
4849 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4850 "Schemas: attribute %s reference %s not found\n",
4851 name, attrDecl->ref);
4852 return;
4853 }
4854 xmlSchemaAttrFixup(ref, ctxt, NULL);
4855 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004856 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004857 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4858 "Schemas: attribute %s has no type nor reference\n",
4859 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004860 }
4861}
4862
4863/**
4864 * xmlSchemaParse:
4865 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004866 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004867 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004868 * XML Shema struture which can be used to validate instances.
4869 * *WARNING* this interface is highly subject to change
4870 *
4871 * Returns the internal XML Schema structure built from the resource or
4872 * NULL in case of error
4873 */
4874xmlSchemaPtr
4875xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4876{
4877 xmlSchemaPtr ret = NULL;
4878 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004879 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004880 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004881 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004882
4883 xmlSchemaInitTypes();
4884
Daniel Veillard6045c902002-10-09 21:13:59 +00004885 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004886 return (NULL);
4887
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004888 nberrors = ctxt->nberrors;
4889 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004890 ctxt->counter = 0;
4891 ctxt->container = NULL;
4892
4893 /*
4894 * First step is to parse the input document into an DOM/Infoset
4895 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004896 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004897 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4898 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004899 if (doc == NULL) {
4900 xmlSchemaPErr(ctxt, NULL,
4901 XML_SCHEMAP_FAILED_LOAD,
4902 "xmlSchemaParse: could not load %s\n",
4903 ctxt->URL, NULL);
4904 return (NULL);
4905 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004906 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004907 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4908 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004909 if (doc == NULL) {
4910 xmlSchemaPErr(ctxt, NULL,
4911 XML_SCHEMAP_FAILED_PARSE,
4912 "xmlSchemaParse: could not parse\n",
4913 NULL, NULL);
4914 return (NULL);
4915 }
4916 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00004917 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00004918 } else if (ctxt->doc != NULL) {
4919 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004920 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00004921 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 xmlSchemaPErr(ctxt, NULL,
4923 XML_SCHEMAP_NOTHING_TO_PARSE,
4924 "xmlSchemaParse: could not parse\n",
4925 NULL, NULL);
4926 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004927 }
4928
4929 /*
4930 * Then extract the root and Schema parse it
4931 */
4932 root = xmlDocGetRootElement(doc);
4933 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004934 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4935 XML_SCHEMAP_NOROOT,
4936 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00004937 if (!preserve) {
4938 xmlFreeDoc(doc);
4939 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004940 return (NULL);
4941 }
4942
4943 /*
4944 * Remove all the blank text nodes
4945 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004946 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00004947
4948 /*
4949 * Then do the parsing for good
4950 */
4951 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004952 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00004953 if (!preserve) {
4954 xmlFreeDoc(doc);
4955 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004956 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004957 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004958 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004959 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00004960
4961 /*
4962 * Then fix all the references.
4963 */
4964 ctxt->schema = ret;
4965 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004966 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004967
4968 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00004969 * Then fixup all attributes declarations
4970 */
4971 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4972
4973 /*
4974 * Then fixup all attributes group declarations
4975 */
4976 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4977 ctxt);
4978
4979 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00004980 * Then fixup all types properties
4981 */
4982 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4983
4984 /*
4985 * Then build the content model for all elements
4986 */
4987 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004988 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004989
4990 /*
4991 * Then check the defaults part of the type like facets values
4992 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004993 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4994 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004995
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004996 if (ctxt->nberrors != 0) {
4997 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004998 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004999 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005000 return (ret);
5001}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005002
Daniel Veillard4255d502002-04-16 15:50:10 +00005003/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00005004 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005005 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005006 * @err: the error callback
5007 * @warn: the warning callback
5008 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005009 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005010 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005011 */
5012void
5013xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005014 xmlSchemaValidityErrorFunc err,
5015 xmlSchemaValidityWarningFunc warn, void *ctx)
5016{
Daniel Veillard4255d502002-04-16 15:50:10 +00005017 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005018 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005019 ctxt->error = err;
5020 ctxt->warning = warn;
5021 ctxt->userData = ctx;
5022}
5023
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005024/**
5025 * xmlSchemaFacetTypeToString:
5026 * @type: the facet type
5027 *
5028 * Convert the xmlSchemaTypeType to a char string.
5029 *
5030 * Returns the char string representation of the facet type if the
5031 * type is a facet and an "Internal Error" string otherwise.
5032 */
5033static const char *
5034xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5035{
5036 switch (type) {
5037 case XML_SCHEMA_FACET_PATTERN:
5038 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005039 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005040 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005041 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005042 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005043 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005044 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005045 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005046 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005047 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005048 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005049 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005050 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005051 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005052 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005053 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005054 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005055 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005056 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005057 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005058 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005059 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005060 return ("fractionDigits");
5061 default:
5062 break;
5063 }
5064 return ("Internal Error");
5065}
5066
5067/**
5068 * xmlSchemaValidateFacets:
5069 * @ctxt: a schema validation context
5070 * @base: the base type
5071 * @facets: the list of facets to check
5072 * @value: the lexical repr of the value to validate
5073 * @val: the precomputed value
5074 *
5075 * Check a value against all facet conditions
5076 *
5077 * Returns 0 if the element is schemas valid, a positive error code
5078 * number otherwise and -1 in case of internal or API error.
5079 */
5080static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005081xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5082 xmlSchemaTypePtr base,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005083 xmlSchemaFacetPtr facets, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005085 int ret = 0;
5086 int tmp = 0;
5087 xmlSchemaTypeType type;
5088 xmlSchemaFacetPtr facet = facets;
5089
5090 while (facet != NULL) {
5091 type = facet->type;
5092 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005093 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005094
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005095 while (facet != NULL) {
5096 tmp =
5097 xmlSchemaValidateFacet(base, facet, value,
5098 ctxt->value);
5099 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005100 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005101 }
5102 facet = facet->next;
5103 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005104 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005105 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005106
5107 if (tmp != 0) {
5108 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005109 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 +00005110 }
5111 if (facet != NULL)
5112 facet = facet->next;
5113 }
5114 return (ret);
5115}
5116
Daniel Veillard4255d502002-04-16 15:50:10 +00005117/************************************************************************
5118 * *
5119 * Simple type validation *
5120 * *
5121 ************************************************************************/
5122
5123/**
5124 * xmlSchemaValidateSimpleValue:
5125 * @ctxt: a schema validation context
5126 * @type: the type declaration
5127 * @value: the value to validate
5128 *
5129 * Validate a value against a simple type
5130 *
5131 * Returns 0 if the value is valid, a positive error code
5132 * number otherwise and -1 in case of internal or API error.
5133 */
5134static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005135xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005136 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005137{
Daniel Veillard4255d502002-04-16 15:50:10 +00005138 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005139
Daniel Veillard4255d502002-04-16 15:50:10 +00005140 /*
5141 * First normalize the value accordingly to Schema Datatype
5142 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5143 */
5144 /*
5145 * Then check the normalized value against the lexical space of the
5146 * type.
5147 */
5148 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005149 if (ctxt->value != NULL) {
5150 xmlSchemaFreeValue(ctxt->value);
5151 ctxt->value = NULL;
5152 }
5153 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5154 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005155 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005156 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 +00005157 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005158 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005159 xmlSchemaTypePtr base;
5160 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005161
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005162 base = type->baseType;
5163 if (base != NULL) {
5164 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5165 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005166 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005168
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005169 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005170 * Do not validate facets or attributes when working on
5171 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005172 */
5173 if (ctxt->schema != NULL) {
5174 if (ret == 0) {
5175 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005176 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 }
5178 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005179 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005180 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005181
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005182 base = type->subtypes;
5183 if (base != NULL) {
5184 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5185 } else {
5186 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005187 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005188 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005189 const xmlChar *cur, *end;
5190 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005192
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005193 base = type->subtypes;
5194 if (base == NULL) {
5195 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5196 "Internal: List type %s has no base type\n",
5197 type->name, NULL);
5198 return (-1);
5199 }
5200 cur = value;
5201 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005202 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005203 cur++;
5204 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005205 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005206 end++;
5207 if (end == cur)
5208 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005209 tmp = xmlStrndup(cur, end - cur);
5210 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
5211 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005212 if (ret2 != 0)
5213 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005214 cur = end;
5215 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005216 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005217 TODO
5218 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005219 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005220}
5221
5222/************************************************************************
5223 * *
5224 * DOM Validation code *
5225 * *
5226 ************************************************************************/
5227
5228static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005229 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005230static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005231 xmlNodePtr elem,
5232 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005233static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005234 xmlNodePtr elem,
5235 xmlSchemaElementPtr elemDecl,
5236 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005237
5238/**
5239 * xmlSchemaRegisterAttributes:
5240 * @ctxt: a schema validation context
5241 * @attrs: a list of attributes
5242 *
5243 * Register the list of attributes as the set to be validated on that element
5244 *
5245 * Returns -1 in case of error, 0 otherwise
5246 */
5247static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005248xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5249{
Daniel Veillard4255d502002-04-16 15:50:10 +00005250 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005251 if ((attrs->ns != NULL) &&
5252 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5253 attrs = attrs->next;
5254 continue;
5255 }
5256 if (ctxt->attrNr >= ctxt->attrMax) {
5257 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005258
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005259 ctxt->attrMax *= 2;
5260 tmp = (xmlSchemaAttrStatePtr)
5261 xmlRealloc(ctxt->attr, ctxt->attrMax *
5262 sizeof(xmlSchemaAttrState));
5263 if (tmp == NULL) {
5264 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5265 ctxt->attrMax /= 2;
5266 return (-1);
5267 }
5268 ctxt->attr = tmp;
5269 }
5270 ctxt->attr[ctxt->attrNr].attr = attrs;
5271 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5272 ctxt->attrNr++;
5273 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005274 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005275 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005276}
5277
5278/**
5279 * xmlSchemaCheckAttributes:
5280 * @ctxt: a schema validation context
5281 * @node: the node carrying it.
5282 *
5283 * Check that the registered set of attributes on the current node
5284 * has been properly validated.
5285 *
5286 * Returns 0 if validity constraints are met, 1 otherwise.
5287 */
5288static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005289xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5290{
Daniel Veillard4255d502002-04-16 15:50:10 +00005291 int ret = 0;
5292 int i;
5293
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005294 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5295 if (ctxt->attr[i].attr == NULL)
5296 break;
5297 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5298 ret = 1;
5299 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5300 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005301 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005302 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005303}
5304
5305/**
5306 * xmlSchemaValidateSimpleContent:
5307 * @ctxt: a schema validation context
5308 * @elem: an element
5309 * @type: the type declaration
5310 *
5311 * Validate the content of an element expected to be a simple type
5312 *
5313 * Returns 0 if the element is schemas valid, a positive error code
5314 * number otherwise and -1 in case of internal or API error.
5315 */
5316static int
5317xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005318 xmlNodePtr node ATTRIBUTE_UNUSED)
5319{
Daniel Veillard4255d502002-04-16 15:50:10 +00005320 xmlNodePtr child;
5321 xmlSchemaTypePtr type, base;
5322 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005323 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005324
5325 child = ctxt->node;
5326 type = ctxt->type;
5327
5328 /*
5329 * Validation Rule: Element Locally Valid (Type): 3.1.3
5330 */
5331 value = xmlNodeGetContent(child);
5332 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5333 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005334 case XML_SCHEMA_TYPE_RESTRICTION:{
5335 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005336
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005337 base = type->baseType;
5338 if (base != NULL) {
5339 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5340 } else {
5341 TODO}
5342 if (ret == 0) {
5343 facet = type->facets;
5344 ret =
5345 xmlSchemaValidateFacets(ctxt, base, facet, value);
5346 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005347 if ((ret == 0) && (type->attributes != NULL)) {
5348 ret = xmlSchemaValidateAttributes(ctxt, node,
5349 type->attributes);
5350 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005351 break;
5352 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005353 case XML_SCHEMA_TYPE_EXTENSION:{
5354 TODO
5355 break;
5356 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005357 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005358 TODO
5359 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005360 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005361 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005362
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005363 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005364}
5365
5366/**
5367 * xmlSchemaValidateCheckNodeList
5368 * @nodelist: the list of nodes
5369 *
5370 * Check the node list is only made of text nodes and entities pointing
5371 * to text nodes
5372 *
5373 * Returns 1 if true, 0 if false and -1 in case of error
5374 */
5375static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5377{
Daniel Veillard4255d502002-04-16 15:50:10 +00005378 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005379 if (nodelist->type == XML_ENTITY_REF_NODE) {
5380 TODO /* implement recursion in the entity content */
5381 }
5382 if ((nodelist->type != XML_TEXT_NODE) &&
5383 (nodelist->type != XML_COMMENT_NODE) &&
5384 (nodelist->type != XML_PI_NODE) &&
5385 (nodelist->type != XML_PI_NODE)) {
5386 return (0);
5387 }
5388 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005389 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005390 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005391}
5392
5393/**
5394 * xmlSchemaSkipIgnored:
5395 * @ctxt: a schema validation context
5396 * @type: the current type context
5397 * @node: the top node.
5398 *
5399 * Skip ignorable nodes in that context
5400 *
5401 * Returns the new sibling
5402 * number otherwise and -1 in case of internal or API error.
5403 */
5404static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005405xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005406 xmlSchemaTypePtr type, xmlNodePtr node)
5407{
Daniel Veillard4255d502002-04-16 15:50:10 +00005408 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005409
Daniel Veillard4255d502002-04-16 15:50:10 +00005410 /*
5411 * TODO complete and handle entities
5412 */
5413 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005414 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005415 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005416 ((node->type == XML_COMMENT_NODE) ||
5417 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5418 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5419 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5420 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005421 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005422 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005423}
5424
5425/**
5426 * xmlSchemaValidateCallback:
5427 * @ctxt: a schema validation context
5428 * @name: the name of the element detected (might be NULL)
5429 * @type: the type
5430 *
5431 * A transition has been made in the automata associated to an element
5432 * content model
5433 */
5434static void
5435xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005436 const xmlChar * name ATTRIBUTE_UNUSED,
5437 xmlSchemaTypePtr type, xmlNodePtr node)
5438{
Daniel Veillard4255d502002-04-16 15:50:10 +00005439 xmlSchemaTypePtr oldtype = ctxt->type;
5440 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005441
Daniel Veillard4255d502002-04-16 15:50:10 +00005442#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005443 xmlGenericError(xmlGenericErrorContext,
5444 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005445 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005446#endif
5447 ctxt->type = type;
5448 ctxt->node = node;
5449 xmlSchemaValidateContent(ctxt, node);
5450 ctxt->type = oldtype;
5451 ctxt->node = oldnode;
5452}
5453
5454
5455#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005456
Daniel Veillard4255d502002-04-16 15:50:10 +00005457/**
5458 * xmlSchemaValidateSimpleRestrictionType:
5459 * @ctxt: a schema validation context
5460 * @node: the top node.
5461 *
5462 * Validate the content of a restriction type.
5463 *
5464 * Returns 0 if the element is schemas valid, a positive error code
5465 * number otherwise and -1 in case of internal or API error.
5466 */
5467static int
5468xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5469 xmlNodePtr node)
5470{
5471 xmlNodePtr child;
5472 xmlSchemaTypePtr type;
5473 int ret;
5474
5475 child = ctxt->node;
5476 type = ctxt->type;
5477
5478 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005479 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005480 return (-1);
5481 }
5482 /*
5483 * Only text and text based entities references shall be found there
5484 */
5485 ret = xmlSchemaValidateCheckNodeList(child);
5486 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005487 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005488 return (-1);
5489 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005490 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 +00005491 return (-1);
5492 }
5493 ctxt->type = type->subtypes;
5494 xmlSchemaValidateContent(ctxt, node);
5495 ctxt->type = type;
5496 return (ret);
5497}
5498#endif
5499
5500/**
5501 * xmlSchemaValidateSimpleType:
5502 * @ctxt: a schema validation context
5503 * @node: the top node.
5504 *
5505 * Validate the content of an simple type.
5506 *
5507 * Returns 0 if the element is schemas valid, a positive error code
5508 * number otherwise and -1 in case of internal or API error.
5509 */
5510static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005511xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5512{
Daniel Veillard4255d502002-04-16 15:50:10 +00005513 xmlNodePtr child;
5514 xmlSchemaTypePtr type;
5515 xmlAttrPtr attr;
5516 int ret;
5517
5518 child = ctxt->node;
5519 type = ctxt->type;
5520
5521 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005522 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5523 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005524 }
5525 /*
5526 * Only text and text based entities references shall be found there
5527 */
5528 ret = xmlSchemaValidateCheckNodeList(child);
5529 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005530 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5531 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005532 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005533 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5534 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005535 }
5536 /*
5537 * Validation Rule: Element Locally Valid (Type): 3.1.1
5538 */
5539 attr = node->properties;
5540 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005541 if ((attr->ns == NULL) ||
5542 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5543 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5544 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5545 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5546 (!xmlStrEqual
5547 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5548 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5549 return (ctxt->err);
5550 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005551 }
5552
5553 ctxt->type = type->subtypes;
5554 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5555 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005556 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005557}
5558
5559/**
5560 * xmlSchemaValidateElementType:
5561 * @ctxt: a schema validation context
5562 * @node: the top node.
5563 *
5564 * Validate the content of an element type.
5565 * Validation Rule: Element Locally Valid (Complex Type)
5566 *
5567 * Returns 0 if the element is schemas valid, a positive error code
5568 * number otherwise and -1 in case of internal or API error.
5569 */
5570static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005571xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5572{
Daniel Veillard4255d502002-04-16 15:50:10 +00005573 xmlNodePtr child;
5574 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005575 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005576 xmlSchemaElementPtr decl;
5577 int ret, attrBase;
5578
5579 oldregexp = ctxt->regexp;
5580
5581 child = ctxt->node;
5582 type = ctxt->type;
5583
5584 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005585 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5586 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005587 }
5588 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005589 if (type->minOccurs > 0) {
5590 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5591 }
5592 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005593 }
5594
5595 /*
5596 * Verify the element matches
5597 */
5598 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005599 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5600 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005601 }
5602 /*
5603 * Verify the attributes
5604 */
5605 attrBase = ctxt->attrBase;
5606 ctxt->attrBase = ctxt->attrNr;
5607 xmlSchemaRegisterAttributes(ctxt, child->properties);
5608 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5609 /*
5610 * Verify the element content recursively
5611 */
5612 decl = (xmlSchemaElementPtr) type;
5613 oldregexp = ctxt->regexp;
5614 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005615 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5616 (xmlRegExecCallbacks)
5617 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005618#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005619 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005620#endif
5621 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5623 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005624
5625 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005627#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005628 xmlGenericError(xmlGenericErrorContext,
5629 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005630#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005631 if (ret == 0) {
5632 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5633 } else if (ret < 0) {
5634 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005635#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005636 } else {
5637 xmlGenericError(xmlGenericErrorContext,
5638 "Element %s content check succeeded\n",
5639 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005640
5641#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 }
5643 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005644 }
5645 /*
5646 * Verify that all attributes were Schemas-validated
5647 */
5648 xmlSchemaCheckAttributes(ctxt, node);
5649 ctxt->attrNr = ctxt->attrBase;
5650 ctxt->attrBase = attrBase;
5651
5652 ctxt->regexp = oldregexp;
5653
5654 ctxt->node = child;
5655 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005656 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005657}
5658
5659/**
5660 * xmlSchemaValidateBasicType:
5661 * @ctxt: a schema validation context
5662 * @node: the top node.
5663 *
5664 * Validate the content of an element expected to be a basic type type
5665 *
5666 * Returns 0 if the element is schemas valid, a positive error code
5667 * number otherwise and -1 in case of internal or API error.
5668 */
5669static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005670xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5671{
Daniel Veillard4255d502002-04-16 15:50:10 +00005672 int ret;
5673 xmlNodePtr child, cur;
5674 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005675 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005676
5677 child = ctxt->node;
5678 type = ctxt->type;
5679
5680 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005681 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5682 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005683 }
5684 /*
5685 * First check the content model of the node.
5686 */
5687 cur = child;
5688 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005689 switch (cur->type) {
5690 case XML_TEXT_NODE:
5691 case XML_CDATA_SECTION_NODE:
5692 case XML_PI_NODE:
5693 case XML_COMMENT_NODE:
5694 case XML_XINCLUDE_START:
5695 case XML_XINCLUDE_END:
5696 break;
5697 case XML_ENTITY_REF_NODE:
5698 case XML_ENTITY_NODE:
5699 TODO break;
5700 case XML_ELEMENT_NODE:
5701 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5702 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005703 case XML_ATTRIBUTE_NODE:
5704 case XML_DOCUMENT_NODE:
5705 case XML_DOCUMENT_TYPE_NODE:
5706 case XML_DOCUMENT_FRAG_NODE:
5707 case XML_NOTATION_NODE:
5708 case XML_HTML_DOCUMENT_NODE:
5709 case XML_DTD_NODE:
5710 case XML_ELEMENT_DECL:
5711 case XML_ATTRIBUTE_DECL:
5712 case XML_ENTITY_DECL:
5713 case XML_NAMESPACE_DECL:
5714#ifdef LIBXML_DOCB_ENABLED
5715 case XML_DOCB_DOCUMENT_NODE:
5716#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005717 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5718 return (ctxt->err);
5719 }
5720 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005721 }
5722 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005723 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005724 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005725 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005726
5727 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005728 xmlSchemaFreeValue(ctxt->value);
5729 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005730 }
5731 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5732 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005733 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005734 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005735 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 +00005736 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005737 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005738}
5739
5740/**
5741 * xmlSchemaValidateComplexType:
5742 * @ctxt: a schema validation context
5743 * @node: the top node.
5744 *
5745 * Validate the content of an element expected to be a complex type type
5746 * xmlschema-1.html#cvc-complex-type
5747 * Validation Rule: Element Locally Valid (Complex Type)
5748 *
5749 * Returns 0 if the element is schemas valid, a positive error code
5750 * number otherwise and -1 in case of internal or API error.
5751 */
5752static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005753xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5754{
Daniel Veillard4255d502002-04-16 15:50:10 +00005755 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005756 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005757 int ret;
5758
5759 child = ctxt->node;
5760 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005761 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005762
Daniel Veillard4255d502002-04-16 15:50:10 +00005763 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005764 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005765 if (type->baseType != NULL) {
5766 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005767 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5768 }
5769 if (type->attributes != NULL) {
5770 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5771 }
5772 subtype = type->subtypes;
5773 while (subtype != NULL) {
5774 ctxt->type = subtype;
5775 xmlSchemaValidateComplexType(ctxt, node);
5776 subtype = subtype->next;
5777 }
5778 break;
5779 case XML_SCHEMA_CONTENT_ELEMENTS:
5780 case XML_SCHEMA_CONTENT_MIXED:
5781 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5782 /*
5783 * Skip ignorable nodes in that context
5784 */
5785 child = xmlSchemaSkipIgnored(ctxt, type, child);
5786 while (child != NULL) {
5787 if (child->type == XML_ELEMENT_NODE) {
5788 ret = xmlRegExecPushString(ctxt->regexp,
5789 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005790#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005791 if (ret < 0)
5792 xmlGenericError(xmlGenericErrorContext,
5793 " --> %s Error\n", child->name);
5794 else
5795 xmlGenericError(xmlGenericErrorContext,
5796 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005797#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005798 }
5799 child = child->next;
5800 /*
5801 * Skip ignorable nodes in that context
5802 */
5803 child = xmlSchemaSkipIgnored(ctxt, type, child);
5804 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005805 if (type->attributes != NULL) {
5806 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 break;
5809 case XML_SCHEMA_CONTENT_BASIC:{
5810 if (type->subtypes != NULL) {
5811 ctxt->type = type->subtypes;
5812 xmlSchemaValidateComplexType(ctxt, node);
5813 }
5814 if (type->baseType != NULL) {
5815 ctxt->type = type->baseType;
5816 xmlSchemaValidateBasicType(ctxt, node);
5817 }
5818 if (type->attributes != NULL) {
5819 xmlSchemaValidateAttributes(ctxt, node,
5820 type->attributes);
5821 }
5822 ctxt->type = type;
5823 break;
5824 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005825 case XML_SCHEMA_CONTENT_SIMPLE:{
5826 if (type->subtypes != NULL) {
5827 ctxt->type = type->subtypes;
5828 xmlSchemaValidateComplexType(ctxt, node);
5829 }
5830 if (type->baseType != NULL) {
5831 ctxt->type = type->baseType;
5832 xmlSchemaValidateComplexType(ctxt, node);
5833 }
5834 if (type->attributes != NULL) {
5835 xmlSchemaValidateAttributes(ctxt, node,
5836 type->attributes);
5837 }
5838 ctxt->type = type;
5839 break;
5840 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005841 default:
5842 TODO xmlGenericError(xmlGenericErrorContext,
5843 "unimplemented content type %d\n",
5844 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005845 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005846 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005847}
5848
5849/**
5850 * xmlSchemaValidateContent:
5851 * @ctxt: a schema validation context
5852 * @elem: an element
5853 * @type: the type declaration
5854 *
5855 * Validate the content of an element against the type.
5856 *
5857 * Returns 0 if the element is schemas valid, a positive error code
5858 * number otherwise and -1 in case of internal or API error.
5859 */
5860static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005861xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5862{
Daniel Veillard4255d502002-04-16 15:50:10 +00005863 xmlNodePtr child;
5864 xmlSchemaTypePtr type;
5865
5866 child = ctxt->node;
5867 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005868 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005869
Daniel Veillarde19fc232002-04-22 16:01:24 +00005870 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005871 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005872
Daniel Veillard4255d502002-04-16 15:50:10 +00005873 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005874 case XML_SCHEMA_TYPE_ANY:
5875 /* Any type will do it, fine */
5876 TODO /* handle recursivity */
5877 break;
5878 case XML_SCHEMA_TYPE_COMPLEX:
5879 xmlSchemaValidateComplexType(ctxt, node);
5880 break;
5881 case XML_SCHEMA_TYPE_ELEMENT:{
5882 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5883
5884 /*
5885 * Handle element reference here
5886 */
5887 if (decl->ref != NULL) {
5888 if (decl->refDecl == NULL) {
5889 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5890 return (-1);
5891 }
5892 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5893 decl = decl->refDecl;
5894 }
5895 xmlSchemaValidateElementType(ctxt, node);
5896 ctxt->type = type;
5897 break;
5898 }
5899 case XML_SCHEMA_TYPE_BASIC:
5900 xmlSchemaValidateBasicType(ctxt, node);
5901 break;
5902 case XML_SCHEMA_TYPE_FACET:
5903 TODO break;
5904 case XML_SCHEMA_TYPE_SIMPLE:
5905 xmlSchemaValidateSimpleType(ctxt, node);
5906 break;
5907 case XML_SCHEMA_TYPE_SEQUENCE:
5908 TODO break;
5909 case XML_SCHEMA_TYPE_CHOICE:
5910 TODO break;
5911 case XML_SCHEMA_TYPE_ALL:
5912 TODO break;
5913 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5914 TODO break;
5915 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5916 TODO break;
5917 case XML_SCHEMA_TYPE_UR:
5918 TODO break;
5919 case XML_SCHEMA_TYPE_RESTRICTION:
5920 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5921 TODO break;
5922 case XML_SCHEMA_TYPE_EXTENSION:
5923 TODO break;
5924 case XML_SCHEMA_TYPE_ATTRIBUTE:
5925 TODO break;
5926 case XML_SCHEMA_TYPE_GROUP:
5927 TODO break;
5928 case XML_SCHEMA_TYPE_NOTATION:
5929 TODO break;
5930 case XML_SCHEMA_TYPE_LIST:
5931 TODO break;
5932 case XML_SCHEMA_TYPE_UNION:
5933 TODO break;
5934 case XML_SCHEMA_FACET_MININCLUSIVE:
5935 TODO break;
5936 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5937 TODO break;
5938 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5939 TODO break;
5940 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5941 TODO break;
5942 case XML_SCHEMA_FACET_TOTALDIGITS:
5943 TODO break;
5944 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5945 TODO break;
5946 case XML_SCHEMA_FACET_PATTERN:
5947 TODO break;
5948 case XML_SCHEMA_FACET_ENUMERATION:
5949 TODO break;
5950 case XML_SCHEMA_FACET_WHITESPACE:
5951 TODO break;
5952 case XML_SCHEMA_FACET_LENGTH:
5953 TODO break;
5954 case XML_SCHEMA_FACET_MAXLENGTH:
5955 TODO break;
5956 case XML_SCHEMA_FACET_MINLENGTH:
5957 TODO break;
5958 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5959 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005960 }
5961 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5962
5963 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005964 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005965 ctxt->node = ctxt->node->next;
5966 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005967 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005968}
5969
5970/**
5971 * xmlSchemaValidateType:
5972 * @ctxt: a schema validation context
5973 * @elem: an element
5974 * @type: the list of type declarations
5975 *
5976 * Validate the content of an element against the types.
5977 *
5978 * Returns 0 if the element is schemas valid, a positive error code
5979 * number otherwise and -1 in case of internal or API error.
5980 */
5981static int
5982xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005983 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5984{
Daniel Veillard4255d502002-04-16 15:50:10 +00005985 xmlChar *nil;
5986
Daniel Veillard2db8c122003-07-08 12:16:59 +00005987 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005988 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005989
Daniel Veillard4255d502002-04-16 15:50:10 +00005990 /*
5991 * 3.3.4 : 2
5992 */
5993 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005994 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5995 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005996 }
5997 /*
5998 * 3.3.4: 3
5999 */
6000 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
6001 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006002 /* 3.3.4: 3.2 */
6003 if (xmlStrEqual(nil, BAD_CAST "true")) {
6004 if (elem->children != NULL) {
6005 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
6006 return (ctxt->err);
6007 }
6008 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6009 (elemDecl->value != NULL)) {
6010 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
6011 return (ctxt->err);
6012 }
6013 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006014 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006015 /* 3.3.4: 3.1 */
6016 if (nil != NULL) {
6017 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
6018 xmlFree(nil);
6019 return (ctxt->err);
6020 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006021 }
6022
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006023 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006024
6025 ctxt->type = elemDecl->subtypes;
6026 ctxt->node = elem->children;
6027 xmlSchemaValidateContent(ctxt, elem);
6028 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006029
6030 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006031}
6032
6033
6034/**
6035 * xmlSchemaValidateAttributes:
6036 * @ctxt: a schema validation context
6037 * @elem: an element
6038 * @attributes: the list of attribute declarations
6039 *
6040 * Validate the attributes of an element.
6041 *
6042 * Returns 0 if the element is schemas valid, a positive error code
6043 * number otherwise and -1 in case of internal or API error.
6044 */
6045static int
6046xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006047 xmlSchemaAttributePtr attributes)
6048{
Daniel Veillard4255d502002-04-16 15:50:10 +00006049 int i, ret;
6050 xmlAttrPtr attr;
6051 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006052 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006053
6054 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006055 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006056 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006057 /*
6058 * Handle attribute groups
6059 */
6060 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6061 group = (xmlSchemaAttributeGroupPtr) attributes;
6062 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6063 attributes = group->next;
6064 continue;
6065 }
6066 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6067 attr = ctxt->attr[i].attr;
6068 if (attr == NULL)
6069 continue;
6070 if (attributes->ref != NULL) {
6071 if (!xmlStrEqual(attr->name, attributes->ref))
6072 continue;
6073 if (attr->ns != NULL) {
6074 if ((attributes->refNs == NULL) ||
6075 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6076 continue;
6077 } else if (attributes->refNs != NULL) {
6078 continue;
6079 }
6080 } else {
6081 if (!xmlStrEqual(attr->name, attributes->name))
6082 continue;
6083 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006084 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006085 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006086 if (attr->ns == NULL) {
6087 /*
6088 * accept an unqualified attribute only if the declaration
6089 * is unqualified or if the schemas allowed it.
6090 */
6091 if ((attributes->targetNamespace != NULL) &&
6092 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6093 continue;
6094 } else {
6095 if (attributes->targetNamespace == NULL)
6096 continue;
6097 if (!xmlStrEqual(attributes->targetNamespace,
6098 attr->ns->href))
6099 continue;
6100 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006101 }
6102 ctxt->cur = (xmlNodePtr) attributes;
6103 if (attributes->subtypes == NULL) {
6104 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6105 continue;
6106 }
6107 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6108 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6109 value);
6110 if (ret != 0) {
6111 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6112 } else {
6113 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6114 }
6115 if (value != NULL) {
6116 xmlFree(value);
6117 }
6118 }
6119 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006120 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006121 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006122}
6123
6124/**
6125 * xmlSchemaValidateElement:
6126 * @ctxt: a schema validation context
6127 * @elem: an element
6128 *
6129 * Validate an element in a tree
6130 *
6131 * Returns 0 if the element is schemas valid, a positive error code
6132 * number otherwise and -1 in case of internal or API error.
6133 */
6134static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006135xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6136{
Daniel Veillard4255d502002-04-16 15:50:10 +00006137 xmlSchemaElementPtr elemDecl;
6138 int ret, attrBase;
6139
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006140 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006141 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6142 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006143 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006144 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6145 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006146 }
6147 /*
6148 * special case whe elementFormDefault is unqualified for top-level elem.
6149 */
6150 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6151 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6152 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6153 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6154 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6155 elem->name, NULL, NULL);
6156 }
6157
Daniel Veillard4255d502002-04-16 15:50:10 +00006158 /*
6159 * 3.3.4 : 1
6160 */
6161 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006162 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6163 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006164 }
6165 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006166 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6167 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006168 }
6169 /*
6170 * Verify the attributes
6171 */
6172 attrBase = ctxt->attrBase;
6173 ctxt->attrBase = ctxt->attrNr;
6174 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6175 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6176 /*
6177 * Verify the element content recursively
6178 */
6179 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006180 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6181 (xmlRegExecCallbacks)
6182 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006183#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006184 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006185#endif
6186 }
6187 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006188 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006190#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006191 xmlGenericError(xmlGenericErrorContext,
6192 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006193#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006194 if (ret == 0) {
6195 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6196 } else if (ret < 0) {
6197 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006198#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006199 } else {
6200 xmlGenericError(xmlGenericErrorContext,
6201 "Element %s content check succeeded\n",
6202 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006203
6204#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006205 }
6206 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006207 }
6208 /*
6209 * Verify that all attributes were Schemas-validated
6210 */
6211 xmlSchemaCheckAttributes(ctxt, elem);
6212 ctxt->attrNr = ctxt->attrBase;
6213 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006214
6215 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006216}
6217
6218/**
6219 * xmlSchemaValidateDocument:
6220 * @ctxt: a schema validation context
6221 * @doc: a parsed document tree
6222 *
6223 * Validate a document tree in memory.
6224 *
6225 * Returns 0 if the document is schemas valid, a positive error code
6226 * number otherwise and -1 in case of internal or API error.
6227 */
6228static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006229xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6230{
Daniel Veillard4255d502002-04-16 15:50:10 +00006231 xmlNodePtr root;
6232 xmlSchemaElementPtr elemDecl;
6233
6234 root = xmlDocGetRootElement(doc);
6235 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006236 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6237 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006238 }
6239 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006240 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6241 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006242 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006243 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6244 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006245 /*
6246 * special case whe elementFormDefault is unqualified for top-level elem.
6247 */
6248 if ((elemDecl == NULL) && (root->ns != NULL) &&
6249 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6250 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6251 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6252 root->name, NULL, NULL);
6253 }
6254
Daniel Veillard4255d502002-04-16 15:50:10 +00006255 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006256 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006257 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006258 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006259 }
6260 /*
6261 * Okay, start the recursive validation
6262 */
6263 xmlSchemaValidateElement(ctxt, root);
6264
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006265 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006266}
6267
6268/************************************************************************
6269 * *
6270 * SAX Validation code *
6271 * *
6272 ************************************************************************/
6273
6274/************************************************************************
6275 * *
6276 * Validation interfaces *
6277 * *
6278 ************************************************************************/
6279
6280/**
6281 * xmlSchemaNewValidCtxt:
6282 * @schema: a precompiled XML Schemas
6283 *
6284 * Create an XML Schemas validation context based on the given schema
6285 *
6286 * Returns the validation context or NULL in case of error
6287 */
6288xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006289xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6290{
Daniel Veillard4255d502002-04-16 15:50:10 +00006291 xmlSchemaValidCtxtPtr ret;
6292
6293 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6294 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006295 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006296 return (NULL);
6297 }
6298 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6299 ret->schema = schema;
6300 ret->attrNr = 0;
6301 ret->attrMax = 10;
6302 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006303 sizeof
6304 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006305 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006306 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6307 free(ret);
6308 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006309 }
6310 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6311 return (ret);
6312}
6313
6314/**
6315 * xmlSchemaFreeValidCtxt:
6316 * @ctxt: the schema validation context
6317 *
6318 * Free the resources associated to the schema validation context
6319 */
6320void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006321xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6322{
Daniel Veillard4255d502002-04-16 15:50:10 +00006323 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006324 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006325 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006326 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006327 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006328 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006329 xmlFree(ctxt);
6330}
6331
6332/**
6333 * xmlSchemaSetValidErrors:
6334 * @ctxt: a schema validation context
6335 * @err: the error function
6336 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006337 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006338 *
6339 * Set the error and warning callback informations
6340 */
6341void
6342xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006343 xmlSchemaValidityErrorFunc err,
6344 xmlSchemaValidityWarningFunc warn, void *ctx)
6345{
Daniel Veillard4255d502002-04-16 15:50:10 +00006346 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006347 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006348 ctxt->error = err;
6349 ctxt->warning = warn;
6350 ctxt->userData = ctx;
6351}
6352
6353/**
6354 * xmlSchemaValidateDoc:
6355 * @ctxt: a schema validation context
6356 * @doc: a parsed document tree
6357 *
6358 * Validate a document tree in memory.
6359 *
6360 * Returns 0 if the document is schemas valid, a positive error code
6361 * number otherwise and -1 in case of internal or API error.
6362 */
6363int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006364xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6365{
Daniel Veillard4255d502002-04-16 15:50:10 +00006366 int ret;
6367
6368 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006369 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006370
6371 ctxt->doc = doc;
6372 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006373 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006374}
6375
6376/**
6377 * xmlSchemaValidateStream:
6378 * @ctxt: a schema validation context
6379 * @input: the input to use for reading the data
6380 * @enc: an optional encoding information
6381 * @sax: a SAX handler for the resulting events
6382 * @user_data: the context to provide to the SAX handler.
6383 *
6384 * Validate a document tree in memory.
6385 *
6386 * Returns 0 if the document is schemas valid, a positive error code
6387 * number otherwise and -1 in case of internal or API error.
6388 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006389int
Daniel Veillard4255d502002-04-16 15:50:10 +00006390xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006391 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6392 xmlSAXHandlerPtr sax, void *user_data)
6393{
Daniel Veillard4255d502002-04-16 15:50:10 +00006394 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006395 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006396 ctxt->input = input;
6397 ctxt->enc = enc;
6398 ctxt->sax = sax;
6399 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006400 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006401}
6402
6403#endif /* LIBXML_SCHEMAS_ENABLED */