blob: 3a3602f0eee99292489d84bd6ca5d6f75fa40f22 [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 Veillardebcdebd2004-03-05 00:15:50 +00001495 if (!strchr(val, ':')) {
1496 ns = xmlSearchNs(node->doc, node, 0);
1497 if (ns) {
1498 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1499 return (val);
1500 }
1501 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001502 ret = xmlSplitQName3(val, &len);
1503 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001504 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001505 }
1506 ret = xmlDictLookup(ctxt->dict, ret, -1);
1507 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001508
1509 ns = xmlSearchNs(node->doc, node, prefix);
1510 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001511 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1512 "Attribute %s: the QName prefix %s is undefined\n",
1513 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001514 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001515 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001516 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001517 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001518}
1519
1520/**
1521 * xmlGetMaxOccurs:
1522 * @ctxt: a schema validation context
1523 * @node: a subtree containing XML Schema informations
1524 *
1525 * Get the maxOccurs property
1526 *
1527 * Returns the default if not found, or the value
1528 */
1529static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001530xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1531{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001532 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001533 int ret = 0;
1534
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001535 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001536 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001537 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001538
1539 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001540 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001541 }
1542
1543 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001544 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001546 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001547 ret = ret * 10 + (*cur - '0');
1548 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001549 }
William M. Brack76e95df2003-10-18 16:20:14 +00001550 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001551 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001552 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001553 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1554 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001555 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001556 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001557 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001558}
1559
1560/**
1561 * xmlGetMinOccurs:
1562 * @ctxt: a schema validation context
1563 * @node: a subtree containing XML Schema informations
1564 *
1565 * Get the minOccurs property
1566 *
1567 * Returns the default if not found, or the value
1568 */
1569static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001570xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1571{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001572 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001573 int ret = 0;
1574
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001575 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001576 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001577 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001578
1579 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001580 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001581 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001582 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001583 ret = ret * 10 + (*cur - '0');
1584 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001585 }
William M. Brack76e95df2003-10-18 16:20:14 +00001586 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001587 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001588 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001589 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1590 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001591 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001592 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001593 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001594}
1595
1596/**
1597 * xmlGetBooleanProp:
1598 * @ctxt: a schema validation context
1599 * @node: a subtree containing XML Schema informations
1600 * @name: the attribute name
1601 * @def: the default value
1602 *
1603 * Get is a bolean property is set
1604 *
1605 * Returns the default if not found, 0 if found to be false,
1606 * 1 if found to be true
1607 */
1608static int
1609xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001610 const char *name, int def)
1611{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001612 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001613
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001614 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001615 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001617
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001618 if (xmlStrEqual(val, BAD_CAST "true"))
1619 def = 1;
1620 else if (xmlStrEqual(val, BAD_CAST "false"))
1621 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001622 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001623 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1624 "Attribute %s: the value %s is not boolean\n",
1625 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001626 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001627 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001628}
1629
1630/************************************************************************
1631 * *
1632 * Shema extraction from an Infoset *
1633 * *
1634 ************************************************************************/
1635static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1636 ctxt, xmlSchemaPtr schema,
1637 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001638static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1639 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001640 xmlSchemaPtr schema,
1641 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001642static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1643 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001644 xmlSchemaPtr schema,
1645 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001646 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001647static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1648 xmlSchemaPtr schema,
1649 xmlNodePtr node);
1650static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1651 xmlSchemaPtr schema,
1652 xmlNodePtr node);
1653static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1654 ctxt,
1655 xmlSchemaPtr schema,
1656 xmlNodePtr node);
1657static xmlSchemaAttributeGroupPtr
1658xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1659 xmlSchemaPtr schema, xmlNodePtr node);
1660static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1661 xmlSchemaPtr schema,
1662 xmlNodePtr node);
1663static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1664 xmlSchemaPtr schema,
1665 xmlNodePtr node);
1666static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001667xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1668 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001669
1670/**
1671 * xmlSchemaParseAttrDecls:
1672 * @ctxt: a schema validation context
1673 * @schema: the schema being built
1674 * @node: a subtree containing XML Schema informations
1675 * @type: the hosting type
1676 *
1677 * parse a XML schema attrDecls declaration corresponding to
1678 * <!ENTITY % attrDecls
1679 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1680 */
1681static xmlNodePtr
1682xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1683 xmlNodePtr child, xmlSchemaTypePtr type)
1684{
1685 xmlSchemaAttributePtr lastattr, attr;
1686
1687 lastattr = NULL;
1688 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001689 (IS_SCHEMA(child, "attributeGroup"))) {
1690 attr = NULL;
1691 if (IS_SCHEMA(child, "attribute")) {
1692 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1693 } else if (IS_SCHEMA(child, "attributeGroup")) {
1694 attr = (xmlSchemaAttributePtr)
1695 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1696 }
1697 if (attr != NULL) {
1698 if (lastattr == NULL) {
1699 type->attributes = attr;
1700 lastattr = attr;
1701 } else {
1702 lastattr->next = attr;
1703 lastattr = attr;
1704 }
1705 }
1706 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001707 }
1708 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001709 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1710 if (attr != NULL) {
1711 if (lastattr == NULL) {
1712 type->attributes = attr;
1713 lastattr = attr;
1714 } else {
1715 lastattr->next = attr;
1716 lastattr = attr;
1717 }
1718 }
1719 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001720 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001721 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001722}
1723
1724/**
1725 * xmlSchemaParseAnnotation:
1726 * @ctxt: a schema validation context
1727 * @schema: the schema being built
1728 * @node: a subtree containing XML Schema informations
1729 *
1730 * parse a XML schema Attrribute declaration
1731 * *WARNING* this interface is highly subject to change
1732 *
1733 * Returns -1 in case of error, 0 if the declaration is inproper and
1734 * 1 in case of success.
1735 */
1736static xmlSchemaAnnotPtr
1737xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1738 xmlNodePtr node)
1739{
1740 xmlSchemaAnnotPtr ret;
1741
1742 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1743 return (NULL);
1744 ret = xmlSchemaNewAnnot(ctxt, node);
1745
1746 return (ret);
1747}
1748
1749/**
1750 * xmlSchemaParseFacet:
1751 * @ctxt: a schema validation context
1752 * @schema: the schema being built
1753 * @node: a subtree containing XML Schema informations
1754 *
1755 * parse a XML schema Facet declaration
1756 * *WARNING* this interface is highly subject to change
1757 *
1758 * Returns the new type structure or NULL in case of error
1759 */
1760static xmlSchemaFacetPtr
1761xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001762 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001763{
1764 xmlSchemaFacetPtr facet;
1765 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001766 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001767
1768 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1769 return (NULL);
1770
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001771 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001772 if (facet == NULL) {
1773 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1774 return (NULL);
1775 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001776 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001777 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001778 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001779 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1780 "Facet %s has no value\n", node->name, NULL);
1781 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001782 return (NULL);
1783 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001784 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001785 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001786 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001787 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001788 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001789 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001790 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001791 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001792 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001793 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001794 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001795 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001796 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001797 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001798 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001799 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001800 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001801 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001802 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001803 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001804 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001805 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1806 } else if (IS_SCHEMA(node, "minLength")) {
1807 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1808 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001809 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1810 "Unknown facet type %s\n", node->name, NULL);
1811 xmlSchemaFreeFacet(facet);
1812 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001813 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001814 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001815 facet->value = value;
1816 child = node->children;
1817
1818 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001819 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1820 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001821 }
1822 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001823 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1824 "Facet %s has unexpected child content\n",
1825 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001826 }
1827 return (facet);
1828}
1829
1830/**
1831 * xmlSchemaParseAny:
1832 * @ctxt: a schema validation context
1833 * @schema: the schema being built
1834 * @node: a subtree containing XML Schema informations
1835 *
1836 * parse a XML schema Any declaration
1837 * *WARNING* this interface is highly subject to change
1838 *
1839 * Returns the new type structure or NULL in case of error
1840 */
1841static xmlSchemaTypePtr
1842xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1843 xmlNodePtr node)
1844{
1845 xmlSchemaTypePtr type;
1846 xmlNodePtr child = NULL;
1847 xmlChar name[30];
1848
1849 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1850 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001851 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001852 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001853 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001854 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001855 type->node = node;
1856 type->type = XML_SCHEMA_TYPE_ANY;
1857 child = node->children;
1858 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1859 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1860
1861 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001862 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1863 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001864 }
1865 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001866 xmlSchemaPErr2(ctxt, node, child,
1867 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1868 "Sequence %s has unexpected content\n", type->name,
1869 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001870 }
1871
1872 return (type);
1873}
1874
1875/**
1876 * xmlSchemaParseNotation:
1877 * @ctxt: a schema validation context
1878 * @schema: the schema being built
1879 * @node: a subtree containing XML Schema informations
1880 *
1881 * parse a XML schema Notation declaration
1882 *
1883 * Returns the new structure or NULL in case of error
1884 */
1885static xmlSchemaNotationPtr
1886xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001887 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001888{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001889 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001890 xmlSchemaNotationPtr ret;
1891 xmlNodePtr child = NULL;
1892
1893 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1894 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001895 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001896 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001897 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1898 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001899 return (NULL);
1900 }
1901 ret = xmlSchemaAddNotation(ctxt, schema, name);
1902 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001903 return (NULL);
1904 }
1905 child = node->children;
1906 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001907 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001909 }
1910 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001911 xmlSchemaPErr2(ctxt, node, child,
1912 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1913 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001914 }
1915
1916 return (ret);
1917}
1918
1919/**
1920 * xmlSchemaParseAnyAttribute:
1921 * @ctxt: a schema validation context
1922 * @schema: the schema being built
1923 * @node: a subtree containing XML Schema informations
1924 *
1925 * parse a XML schema AnyAttrribute declaration
1926 * *WARNING* this interface is highly subject to change
1927 *
1928 * Returns an attribute def structure or NULL
1929 */
1930static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001931xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1932 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001933{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001934 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001935 xmlSchemaAttributePtr ret;
1936 xmlNodePtr child = NULL;
1937 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001938 const xmlChar *local, *ns;
1939
Daniel Veillard4255d502002-04-16 15:50:10 +00001940
1941 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1942 return (NULL);
1943
1944 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001945 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1946 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001947 if (ret == NULL) {
1948 return (NULL);
1949 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001950 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1951 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001952 if ((processContents == NULL)
1953 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1954 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1955 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1956 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1957 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1958 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001959 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001960 xmlSchemaPErr2(ctxt, node, child,
1961 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1962 "anyAttribute has unexpected content for processContents: %s\n",
1963 processContents, NULL);
1964 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001965 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001966
1967 child = node->children;
1968 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001969 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1970 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001971 }
1972 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001973 xmlSchemaPErr2(ctxt, node, child,
1974 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1975 "anyAttribute %s has unexpected content\n",
1976 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001977 }
1978
1979 return (ret);
1980}
1981
1982
1983/**
1984 * xmlSchemaParseAttribute:
1985 * @ctxt: a schema validation context
1986 * @schema: the schema being built
1987 * @node: a subtree containing XML Schema informations
1988 *
1989 * parse a XML schema Attrribute declaration
1990 * *WARNING* this interface is highly subject to change
1991 *
1992 * Returns -1 in case of error, 0 if the declaration is inproper and
1993 * 1 in case of success.
1994 */
1995static xmlSchemaAttributePtr
1996xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1997 xmlNodePtr node)
1998{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001999 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002000 xmlSchemaAttributePtr ret;
2001 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002002 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002003
2004 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2005 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002006 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002007 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002008
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002009 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2010 if (ref == NULL) {
2011 xmlSchemaPErr2(ctxt, node, child,
2012 XML_SCHEMAP_ATTR_NONAME_NOREF,
2013 "Attribute has no name nor ref\n", NULL, NULL);
2014 return (NULL);
2015 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002016 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2017 name = (const xmlChar *) buf;
2018 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2019 } else {
2020 const xmlChar *local, *ns;
2021
2022 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2023 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002024 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002025 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002026 return (NULL);
2027 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002028 ret->ref = ref;
2029 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002030 if ((ret->targetNamespace != NULL) &&
2031 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2032 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2033 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002034 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002035 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002036 child = node->children;
2037 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002038 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2039 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002040 }
2041 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002042 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2043 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002044 }
2045 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002046 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2047 "attribute %s has unexpected content\n", name,
2048 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002049 }
2050
2051 return (ret);
2052}
2053
2054/**
2055 * xmlSchemaParseAttributeGroup:
2056 * @ctxt: a schema validation context
2057 * @schema: the schema being built
2058 * @node: a subtree containing XML Schema informations
2059 *
2060 * parse a XML schema Attribute Group declaration
2061 * *WARNING* this interface is highly subject to change
2062 *
2063 * Returns the attribute group or NULL in case of error.
2064 */
2065static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002066xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2067 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002068{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002069 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002070 xmlSchemaAttributeGroupPtr ret;
2071 xmlSchemaAttributePtr last = NULL, attr;
2072 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002073 const xmlChar *oldcontainer;
2074 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002075
2076 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2077 return (NULL);
2078 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002079 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002080 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002081
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002082 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2083 if (ref == NULL) {
2084 xmlSchemaPErr2(ctxt, node, child,
2085 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2086 "AttributeGroup has no name nor ref\n", NULL,
2087 NULL);
2088 return (NULL);
2089 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002090 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2091 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002092 if (name == NULL) {
2093 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2094 return (NULL);
2095 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002096 }
2097 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2098 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002099 return (NULL);
2100 }
2101 ret->ref = ref;
2102 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002103 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002104 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002105 child = node->children;
2106 ctxt->container = name;
2107 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002108 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2109 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002110 }
2111 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002112 (IS_SCHEMA(child, "attributeGroup"))) {
2113 attr = NULL;
2114 if (IS_SCHEMA(child, "attribute")) {
2115 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2116 } else if (IS_SCHEMA(child, "attributeGroup")) {
2117 attr = (xmlSchemaAttributePtr)
2118 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2119 }
2120 if (attr != NULL) {
2121 if (last == NULL) {
2122 ret->attributes = attr;
2123 last = attr;
2124 } else {
2125 last->next = attr;
2126 last = attr;
2127 }
2128 }
2129 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002130 }
2131 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002132 TODO
2133 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002134 }
2135 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002136 xmlSchemaPErr2(ctxt, node, child,
2137 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2138 "attribute group %s has unexpected content\n", name,
2139 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002140 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002141 ctxt->container = oldcontainer;
2142 return (ret);
2143}
2144
2145/**
2146 * xmlSchemaParseElement:
2147 * @ctxt: a schema validation context
2148 * @schema: the schema being built
2149 * @node: a subtree containing XML Schema informations
2150 *
2151 * parse a XML schema Element declaration
2152 * *WARNING* this interface is highly subject to change
2153 *
2154 * Returns -1 in case of error, 0 if the declaration is inproper and
2155 * 1 in case of success.
2156 */
2157static xmlSchemaElementPtr
2158xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2159 xmlNodePtr node, int toplevel)
2160{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002161 const xmlChar *name, *fixed;
2162 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002163 xmlSchemaElementPtr ret;
2164 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002165 const xmlChar *oldcontainer;
2166 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002167
2168 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2169 return (NULL);
2170 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002171 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002172 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002173
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002174 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2175 if (ref == NULL) {
2176 xmlSchemaPErr2(ctxt, node, child,
2177 XML_SCHEMAP_ELEM_NONAME_NOREF,
2178 "Element has no name nor ref\n", NULL, NULL);
2179 return (NULL);
2180 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002181 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2182 name = (const xmlChar *) buf;
2183 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2184 } else {
2185 const xmlChar *local, *ns;
2186
2187 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2188 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002189 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002190 if (ret != NULL)
2191 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002192 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002193 return (NULL);
2194 }
2195 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2196 ret->ref = ref;
2197 ret->refNs = refNs;
2198 if (ref != NULL)
2199 ret->flags |= XML_SCHEMAS_ELEM_REF;
2200 if (toplevel)
2201 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2202 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2203 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2204 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2205 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2206 ctxt->container = name;
2207
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002208 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002209 ret->namedType =
2210 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
2211 ret->substGroup =
2212 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2213 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002214 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002215 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2216 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002217
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002218 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002220 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2221 "Element %s has both default and fixed\n",
2222 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002223 } else if (fixed != NULL) {
2224 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002225 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002226 }
2227
2228 child = node->children;
2229 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002230 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2231 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002232 }
2233 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002234 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002235 child = child->next;
2236 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002237 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002238 child = child->next;
2239 }
2240 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002241 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2242 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002243 }
2244 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002245 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2246 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002247 }
2248
2249 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002250 return (ret);
2251}
2252
2253/**
2254 * xmlSchemaParseUnion:
2255 * @ctxt: a schema validation context
2256 * @schema: the schema being built
2257 * @node: a subtree containing XML Schema informations
2258 *
2259 * parse a XML schema Union definition
2260 * *WARNING* this interface is highly subject to change
2261 *
2262 * Returns -1 in case of error, 0 if the declaration is inproper and
2263 * 1 in case of success.
2264 */
2265static xmlSchemaTypePtr
2266xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002267 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002268{
2269 xmlSchemaTypePtr type, subtype, last = NULL;
2270 xmlNodePtr child = NULL;
2271 xmlChar name[30];
2272
2273 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2274 return (NULL);
2275
2276
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002277 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002278 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002279 if (type == NULL)
2280 return (NULL);
2281 type->node = node;
2282 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002283 type->id = xmlSchemaGetProp(ctxt, node, "id");
2284 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002285
2286 child = node->children;
2287 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002288 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2289 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002290 }
2291 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002292 subtype = (xmlSchemaTypePtr)
2293 xmlSchemaParseSimpleType(ctxt, schema, child);
2294 if (subtype != NULL) {
2295 if (last == NULL) {
2296 type->subtypes = subtype;
2297 last = subtype;
2298 } else {
2299 last->next = subtype;
2300 last = subtype;
2301 }
2302 last->next = NULL;
2303 }
2304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002305 }
2306 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002307 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2308 "Union %s has unexpected content\n", type->name,
2309 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002310 }
2311 return (type);
2312}
2313
2314/**
2315 * xmlSchemaParseList:
2316 * @ctxt: a schema validation context
2317 * @schema: the schema being built
2318 * @node: a subtree containing XML Schema informations
2319 *
2320 * parse a XML schema List definition
2321 * *WARNING* this interface is highly subject to change
2322 *
2323 * Returns -1 in case of error, 0 if the declaration is inproper and
2324 * 1 in case of success.
2325 */
2326static xmlSchemaTypePtr
2327xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002328 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002329{
2330 xmlSchemaTypePtr type, subtype;
2331 xmlNodePtr child = NULL;
2332 xmlChar name[30];
2333
2334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2335 return (NULL);
2336
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002337 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002338 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002339 if (type == NULL)
2340 return (NULL);
2341 type->node = node;
2342 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002343 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002344 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
2345
2346 child = node->children;
2347 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002348 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2349 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002350 }
2351 subtype = NULL;
2352 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002353 subtype = (xmlSchemaTypePtr)
2354 xmlSchemaParseSimpleType(ctxt, schema, child);
2355 child = child->next;
2356 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002357 }
2358 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002359 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2360 "List %s has unexpected content\n", type->name,
2361 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002362 }
2363 return (type);
2364}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002365
Daniel Veillard4255d502002-04-16 15:50:10 +00002366/**
2367 * xmlSchemaParseSimpleType:
2368 * @ctxt: a schema validation context
2369 * @schema: the schema being built
2370 * @node: a subtree containing XML Schema informations
2371 *
2372 * parse a XML schema Simple Type definition
2373 * *WARNING* this interface is highly subject to change
2374 *
2375 * Returns -1 in case of error, 0 if the declaration is inproper and
2376 * 1 in case of success.
2377 */
2378static xmlSchemaTypePtr
2379xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2380 xmlNodePtr node)
2381{
2382 xmlSchemaTypePtr type, subtype;
2383 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002384 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002385
2386 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2387 return (NULL);
2388
2389
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002390 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002391 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002392 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002393
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002394 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2395 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2396 } else {
2397 const xmlChar *local, *ns;
2398
2399 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2400 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002401 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002402 if (type == NULL)
2403 return (NULL);
2404 type->node = node;
2405 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002406 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002407
2408 child = node->children;
2409 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002410 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2411 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002412 }
2413 subtype = NULL;
2414 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 subtype = (xmlSchemaTypePtr)
2416 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2417 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002418 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002419 subtype = (xmlSchemaTypePtr)
2420 xmlSchemaParseList(ctxt, schema, child);
2421 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002422 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002423 subtype = (xmlSchemaTypePtr)
2424 xmlSchemaParseUnion(ctxt, schema, child);
2425 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002426 }
2427 type->subtypes = subtype;
2428 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002429 xmlSchemaPErr2(ctxt, node, child,
2430 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2431 "SimpleType %s has unexpected content\n",
2432 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002433 }
2434
2435 return (type);
2436}
2437
2438
2439/**
2440 * xmlSchemaParseGroup:
2441 * @ctxt: a schema validation context
2442 * @schema: the schema being built
2443 * @node: a subtree containing XML Schema informations
2444 *
2445 * parse a XML schema Group definition
2446 * *WARNING* this interface is highly subject to change
2447 *
2448 * Returns -1 in case of error, 0 if the declaration is inproper and
2449 * 1 in case of success.
2450 */
2451static xmlSchemaTypePtr
2452xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002453 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002454{
2455 xmlSchemaTypePtr type, subtype;
2456 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002457 const xmlChar *name;
2458 const xmlChar *ref = NULL, *refNs = NULL;
2459 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002460
2461 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2462 return (NULL);
2463
2464
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002465 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002466 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002467
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002468 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2469 if (ref == NULL) {
2470 xmlSchemaPErr2(ctxt, node, child,
2471 XML_SCHEMAP_GROUP_NONAME_NOREF,
2472 "Group has no name nor ref\n", NULL, NULL);
2473 return (NULL);
2474 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002475 if (refNs == NULL)
2476 refNs = schema->targetNamespace;
2477 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2478 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002479 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002480 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002481 if (type == NULL)
2482 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002483
Daniel Veillard4255d502002-04-16 15:50:10 +00002484 type->node = node;
2485 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002486 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002487 type->ref = ref;
2488 type->refNs = refNs;
2489 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2490 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2491
2492 child = node->children;
2493 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002494 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2495 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002496 }
2497 subtype = NULL;
2498 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002499 subtype = (xmlSchemaTypePtr)
2500 xmlSchemaParseAll(ctxt, schema, child);
2501 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002502 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002503 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2504 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002505 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002506 subtype = (xmlSchemaTypePtr)
2507 xmlSchemaParseSequence(ctxt, schema, child);
2508 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002509 }
2510 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002511 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002512 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002513 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2514 "Group %s has unexpected content\n", type->name,
2515 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002516 }
2517
2518 return (type);
2519}
2520
2521/**
2522 * xmlSchemaParseAll:
2523 * @ctxt: a schema validation context
2524 * @schema: the schema being built
2525 * @node: a subtree containing XML Schema informations
2526 *
2527 * parse a XML schema All definition
2528 * *WARNING* this interface is highly subject to change
2529 *
2530 * Returns -1 in case of error, 0 if the declaration is inproper and
2531 * 1 in case of success.
2532 */
2533static xmlSchemaTypePtr
2534xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002535 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002536{
2537 xmlSchemaTypePtr type, subtype, last = NULL;
2538 xmlNodePtr child = NULL;
2539 xmlChar name[30];
2540
2541 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2542 return (NULL);
2543
2544
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002545 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002546 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002547 if (type == NULL)
2548 return (NULL);
2549 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002550 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002551 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002552 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002553 if (type->minOccurs > 1)
2554 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2555 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002556 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002557 if (type->maxOccurs > 1)
2558 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2559 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002560
2561 child = node->children;
2562 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002563 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2564 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002565 }
2566 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002567 subtype = (xmlSchemaTypePtr)
2568 xmlSchemaParseElement(ctxt, schema, child, 0);
2569 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002570 if (subtype->minOccurs > 1)
2571 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2572 "invalid value for minOccurs (must be 0 or 1)\n",
2573 NULL, NULL);
2574 if (subtype->maxOccurs > 1)
2575 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2576 "invalid value for maxOccurs (must be 0 or 1)\n",
2577 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002578 if (last == NULL) {
2579 type->subtypes = subtype;
2580 last = subtype;
2581 } else {
2582 last->next = subtype;
2583 last = subtype;
2584 }
2585 last->next = NULL;
2586 }
2587 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002588 }
2589 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002590 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2591 "All %s has unexpected content\n", type->name,
2592 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002593 }
2594
2595 return (type);
2596}
2597
2598/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002599 * xmlSchemaImportSchema
2600 *
2601 * @ctxt: a schema validation context
2602 * @schemaLocation: an URI defining where to find the imported schema
2603 *
2604 * import a XML schema
2605 * *WARNING* this interface is highly subject to change
2606 *
2607 * Returns -1 in case of error and 1 in case of success.
2608 */
2609static xmlSchemaImportPtr
2610xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2611 const xmlChar *schemaLocation)
2612{
2613 xmlSchemaImportPtr import;
2614 xmlSchemaParserCtxtPtr newctxt;
2615
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002616 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002617 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002618 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002619 NULL);
2620 return (NULL);
2621 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002622 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2623 /* Keep the same dictionnary for parsing, really */
2624 xmlDictReference(ctxt->dict);
2625 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002626 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002627 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2628
Daniel Veillard1d913862003-11-21 00:28:39 +00002629 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2630 ctxt->userData);
2631
2632 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2633 if (import == NULL) {
2634 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2635 NULL);
2636 xmlSchemaFreeParserCtxt(newctxt);
2637 return (NULL);
2638 }
2639
2640 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002641 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002642 import->schema = xmlSchemaParse(newctxt);
2643
2644 if (import->schema == NULL) {
2645 /* FIXME use another error enum here ? */
2646 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2647 "failed to import schema at location %s\n",
2648 schemaLocation, NULL);
2649
2650 xmlSchemaFreeParserCtxt(newctxt);
2651 if (import->schemaLocation != NULL)
2652 xmlFree((xmlChar *)import->schemaLocation);
2653 xmlFree(import);
2654 return NULL;
2655 }
2656
2657 xmlSchemaFreeParserCtxt(newctxt);
2658 return import;
2659}
2660
2661
2662/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002663 * xmlSchemaParseImport:
2664 * @ctxt: a schema validation context
2665 * @schema: the schema being built
2666 * @node: a subtree containing XML Schema informations
2667 *
2668 * parse a XML schema Import definition
2669 * *WARNING* this interface is highly subject to change
2670 *
2671 * Returns -1 in case of error, 0 if the declaration is inproper and
2672 * 1 in case of success.
2673 */
2674static int
2675xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002676 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002677{
2678 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002679 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002680 const xmlChar *namespace;
2681 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002682 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002683 xmlURIPtr check;
2684
Daniel Veillard1d913862003-11-21 00:28:39 +00002685
Daniel Veillard5a872412002-05-22 06:40:27 +00002686 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2687 return (-1);
2688
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002689 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002690 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002691 check = xmlParseURI((const char *) namespace);
2692 if (check == NULL) {
2693 xmlSchemaPErr2(ctxt, node, child,
2694 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2695 "Import namespace attribute is not an URI: %s\n",
2696 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002697 return (-1);
2698 } else {
2699 xmlFreeURI(check);
2700 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002701 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002702 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002703 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002704 xmlChar *base = NULL;
2705 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002706 check = xmlParseURI((const char *) schemaLocation);
2707 if (check == NULL) {
2708 xmlSchemaPErr2(ctxt, node, child,
2709 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2710 "Import schemaLocation attribute is not an URI: %s\n",
2711 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002712 return (-1);
2713 } else {
2714 xmlFreeURI(check);
2715 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002716 base = xmlNodeGetBase(node->doc, node);
2717 if (base == NULL) {
2718 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2719 } else {
2720 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002721 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002722 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002723 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002724 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2725 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002726 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002727 }
2728 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002729 schema->schemasImports = xmlHashCreate(10);
2730 if (schema->schemasImports == NULL) {
2731 xmlSchemaPErr2(ctxt, node, child,
2732 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2733 "Internal: failed to build import table\n",
2734 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002735 return (-1);
2736 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002737 }
2738 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002739 import = xmlHashLookup(schema->schemasImports,
2740 XML_SCHEMAS_DEFAULT_NAMESPACE);
2741 if (import != NULL)
2742 previous = import->schemaLocation;
2743 else
2744 previous = NULL;
2745
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002746 if (schemaLocation != NULL) {
2747 if (previous != NULL) {
2748 if (!xmlStrEqual(schemaLocation, previous)) {
2749 xmlSchemaPErr2(ctxt, node, child,
2750 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2751 "Redefining import for default namespace with a different URI: %s\n",
2752 schemaLocation, NULL);
2753 }
2754 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002755 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2756 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002757 return (-1);
2758 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002759 xmlHashAddEntry(schema->schemasImports,
2760 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002761 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002762 }
2763 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002764 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002765 import = xmlHashLookup(schema->schemasImports, namespace);
2766 if (import != NULL)
2767 previous = import->schemaLocation;
2768 else
2769 previous = NULL;
2770
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002771 if (schemaLocation != NULL) {
2772 if (previous != NULL) {
2773 if (!xmlStrEqual(schemaLocation, previous)) {
2774 xmlSchemaPErr2(ctxt, node, child,
2775 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2776 "Redefining import for namespace %s with a different URI: %s\n",
2777 namespace, schemaLocation);
2778 }
2779 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002780 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2781 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002782 return (-1);
2783 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002784 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002785 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002786 }
2787 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002788 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002789
2790 child = node->children;
2791 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002792 /*
2793 * the annotations here are simply discarded ...
2794 */
2795 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002796 }
2797 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002798 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2799 "Import has unexpected content\n", NULL, NULL);
2800 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002801 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002802 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002803}
2804
2805/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002806 * xmlSchemaCleanupDoc:
2807 * @ctxt: a schema validation context
2808 * @node: the root of the document.
2809 *
2810 * removes unwanted nodes in a schemas document tree
2811 */
2812static void
2813xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
2814{
2815 xmlNodePtr delete, cur;
2816
2817 if ((ctxt == NULL) || (root == NULL)) return;
2818
2819 /*
2820 * Remove all the blank text nodes
2821 */
2822 delete = NULL;
2823 cur = root;
2824 while (cur != NULL) {
2825 if (delete != NULL) {
2826 xmlUnlinkNode(delete);
2827 xmlFreeNode(delete);
2828 delete = NULL;
2829 }
2830 if (cur->type == XML_TEXT_NODE) {
2831 if (IS_BLANK_NODE(cur)) {
2832 if (xmlNodeGetSpacePreserve(cur) != 1) {
2833 delete = cur;
2834 }
2835 }
2836 } else if ((cur->type != XML_ELEMENT_NODE) &&
2837 (cur->type != XML_CDATA_SECTION_NODE)) {
2838 delete = cur;
2839 goto skip_children;
2840 }
2841
2842 /*
2843 * Skip to next node
2844 */
2845 if (cur->children != NULL) {
2846 if ((cur->children->type != XML_ENTITY_DECL) &&
2847 (cur->children->type != XML_ENTITY_REF_NODE) &&
2848 (cur->children->type != XML_ENTITY_NODE)) {
2849 cur = cur->children;
2850 continue;
2851 }
2852 }
2853 skip_children:
2854 if (cur->next != NULL) {
2855 cur = cur->next;
2856 continue;
2857 }
2858
2859 do {
2860 cur = cur->parent;
2861 if (cur == NULL)
2862 break;
2863 if (cur == root) {
2864 cur = NULL;
2865 break;
2866 }
2867 if (cur->next != NULL) {
2868 cur = cur->next;
2869 break;
2870 }
2871 } while (cur != NULL);
2872 }
2873 if (delete != NULL) {
2874 xmlUnlinkNode(delete);
2875 xmlFreeNode(delete);
2876 delete = NULL;
2877 }
2878}
2879
2880/**
2881 * xmlSchemaParseSchemaTopLevel:
2882 * @ctxt: a schema validation context
2883 * @schema: the schemas
2884 * @nodes: the list of top level nodes
2885 *
2886 * Returns the internal XML Schema structure built from the resource or
2887 * NULL in case of error
2888 */
2889static void
2890xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
2891 xmlSchemaPtr schema, xmlNodePtr nodes)
2892{
2893 xmlNodePtr child;
2894 xmlSchemaAnnotPtr annot;
2895
2896 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
2897 return;
2898
2899 child = nodes;
2900 while ((IS_SCHEMA(child, "include")) ||
2901 (IS_SCHEMA(child, "import")) ||
2902 (IS_SCHEMA(child, "redefine")) ||
2903 (IS_SCHEMA(child, "annotation"))) {
2904 if (IS_SCHEMA(child, "annotation")) {
2905 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2906 if (schema->annot == NULL)
2907 schema->annot = annot;
2908 else
2909 xmlSchemaFreeAnnot(annot);
2910 } else if (IS_SCHEMA(child, "import")) {
2911 xmlSchemaParseImport(ctxt, schema, child);
2912 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002913 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002914 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002915 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002916 } else if (IS_SCHEMA(child, "redefine")) {
2917 TODO
2918 }
2919 child = child->next;
2920 }
2921 while (child != NULL) {
2922 if (IS_SCHEMA(child, "complexType")) {
2923 xmlSchemaParseComplexType(ctxt, schema, child);
2924 child = child->next;
2925 } else if (IS_SCHEMA(child, "simpleType")) {
2926 xmlSchemaParseSimpleType(ctxt, schema, child);
2927 child = child->next;
2928 } else if (IS_SCHEMA(child, "element")) {
2929 xmlSchemaParseElement(ctxt, schema, child, 1);
2930 child = child->next;
2931 } else if (IS_SCHEMA(child, "attribute")) {
2932 xmlSchemaParseAttribute(ctxt, schema, child);
2933 child = child->next;
2934 } else if (IS_SCHEMA(child, "attributeGroup")) {
2935 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2936 child = child->next;
2937 } else if (IS_SCHEMA(child, "group")) {
2938 xmlSchemaParseGroup(ctxt, schema, child);
2939 child = child->next;
2940 } else if (IS_SCHEMA(child, "notation")) {
2941 xmlSchemaParseNotation(ctxt, schema, child);
2942 child = child->next;
2943 } else {
2944 xmlSchemaPErr2(ctxt, NULL, child,
2945 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
2946 "Schemas: unexpected element %s here \n",
2947 child->name, NULL);
2948 child = child->next;
2949 }
2950 while (IS_SCHEMA(child, "annotation")) {
2951 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2952 if (schema->annot == NULL)
2953 schema->annot = annot;
2954 else
2955 xmlSchemaFreeAnnot(annot);
2956 child = child->next;
2957 }
2958 }
2959}
2960
2961/**
2962 * xmlSchemaParseInclude:
2963 * @ctxt: a schema validation context
2964 * @schema: the schema being built
2965 * @node: a subtree containing XML Schema informations
2966 *
2967 * parse a XML schema Include definition
2968 *
2969 * Returns -1 in case of error, 0 if the declaration is inproper and
2970 * 1 in case of success.
2971 */
2972static int
2973xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2974 xmlNodePtr node)
2975{
2976 xmlNodePtr child = NULL;
2977 const xmlChar *schemaLocation;
2978 xmlURIPtr check;
2979 xmlDocPtr doc;
2980 xmlNodePtr root;
2981 xmlSchemaIncludePtr include;
2982
2983
2984 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2985 return (-1);
2986
2987 /*
2988 * Preliminary step, extract the URI-Reference for the include and
2989 * make an URI from the base.
2990 */
2991 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
2992 if (schemaLocation != NULL) {
2993 xmlChar *base = NULL;
2994 xmlChar *URI = NULL;
2995 check = xmlParseURI((const char *) schemaLocation);
2996 if (check == NULL) {
2997 xmlSchemaPErr2(ctxt, node, child,
2998 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
2999 "Include schemaLocation attribute is not an URI: %s\n",
3000 schemaLocation, NULL);
3001 return (-1);
3002 } else {
3003 xmlFreeURI(check);
3004 }
3005 base = xmlNodeGetBase(node->doc, node);
3006 if (base == NULL) {
3007 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3008 } else {
3009 URI = xmlBuildURI(schemaLocation, base);
3010 xmlFree(base);
3011 }
3012 if (URI != NULL) {
3013 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3014 xmlFree(URI);
3015 }
3016 } else {
3017 xmlSchemaPErr2(ctxt, node, child,
3018 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3019 "Include schemaLocation attribute missing\n",
3020 NULL, NULL);
3021 return (-1);
3022 }
3023
3024 child = node->children;
3025 while (IS_SCHEMA(child, "annotation")) {
3026 /*
3027 * the annotations here are simply discarded ...
3028 */
3029 child = child->next;
3030 }
3031 if (child != NULL) {
3032 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3033 "Include has unexpected content\n", NULL, NULL);
3034 return (-1);
3035 }
3036
3037 /*
3038 * First step is to parse the input document into an DOM/Infoset
3039 */
3040 doc = xmlReadFile((const char *) schemaLocation, NULL,
3041 SCHEMAS_PARSE_OPTIONS);
3042 if (doc == NULL) {
3043 xmlSchemaPErr(ctxt, NULL,
3044 XML_SCHEMAP_FAILED_LOAD,
3045 "xmlSchemaParse: could not load %s\n",
3046 ctxt->URL, NULL);
3047 return(-1);
3048 }
3049
3050 /*
3051 * Then extract the root of the schema
3052 */
3053 root = xmlDocGetRootElement(doc);
3054 if (root == NULL) {
3055 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3056 XML_SCHEMAP_NOROOT,
3057 "schemas %s has no root", schemaLocation, NULL);
3058 xmlFreeDoc(doc);
3059 return (-1);
3060 }
3061
3062 /*
3063 * Remove all the blank text nodes
3064 */
3065 xmlSchemaCleanupDoc(ctxt, root);
3066
3067 /*
3068 * Check the schemas top level element
3069 */
3070 if (!IS_SCHEMA(root, "schema")) {
3071 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3072 XML_SCHEMAP_NOT_SCHEMA,
3073 "File %s is not a schemas", schemaLocation, NULL);
3074 xmlFreeDoc(doc);
3075 return (-1);
3076 }
3077
3078 /*
3079 * register the include
3080 */
3081 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3082 if (include == NULL) {
3083 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3084 xmlFreeDoc(doc);
3085 return (-1);
3086 }
3087
3088 memset(include, 0, sizeof(xmlSchemaInclude));
3089 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3090 include->doc = doc;
3091 include->next = schema->includes;
3092 schema->includes = include;
3093
3094
3095 /*
3096 * parse the declarations in the included file like if they
3097 * were in the original file.
3098 */
3099 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3100
3101 return (1);
3102}
3103
3104/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003105 * xmlSchemaParseChoice:
3106 * @ctxt: a schema validation context
3107 * @schema: the schema being built
3108 * @node: a subtree containing XML Schema informations
3109 *
3110 * parse a XML schema Choice definition
3111 * *WARNING* this interface is highly subject to change
3112 *
3113 * Returns -1 in case of error, 0 if the declaration is inproper and
3114 * 1 in case of success.
3115 */
3116static xmlSchemaTypePtr
3117xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003118 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003119{
3120 xmlSchemaTypePtr type, subtype, last = NULL;
3121 xmlNodePtr child = NULL;
3122 xmlChar name[30];
3123
3124 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3125 return (NULL);
3126
3127
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003128 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003129 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003130 if (type == NULL)
3131 return (NULL);
3132 type->node = node;
3133 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003134 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003135 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3136 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3137
3138 child = node->children;
3139 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003140 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3141 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003142 }
3143 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003144 (IS_SCHEMA(child, "group")) ||
3145 (IS_SCHEMA(child, "any")) ||
3146 (IS_SCHEMA(child, "choice")) ||
3147 (IS_SCHEMA(child, "sequence"))) {
3148 subtype = NULL;
3149 if (IS_SCHEMA(child, "element")) {
3150 subtype = (xmlSchemaTypePtr)
3151 xmlSchemaParseElement(ctxt, schema, child, 0);
3152 } else if (IS_SCHEMA(child, "group")) {
3153 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3154 } else if (IS_SCHEMA(child, "any")) {
3155 subtype = xmlSchemaParseAny(ctxt, schema, child);
3156 } else if (IS_SCHEMA(child, "sequence")) {
3157 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3158 } else if (IS_SCHEMA(child, "choice")) {
3159 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3160 }
3161 if (subtype != NULL) {
3162 if (last == NULL) {
3163 type->subtypes = subtype;
3164 last = subtype;
3165 } else {
3166 last->next = subtype;
3167 last = subtype;
3168 }
3169 last->next = NULL;
3170 }
3171 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003172 }
3173 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003174 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3175 "Choice %s has unexpected content\n", type->name,
3176 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 }
3178
3179 return (type);
3180}
3181
3182/**
3183 * xmlSchemaParseSequence:
3184 * @ctxt: a schema validation context
3185 * @schema: the schema being built
3186 * @node: a subtree containing XML Schema informations
3187 *
3188 * parse a XML schema Sequence definition
3189 * *WARNING* this interface is highly subject to change
3190 *
3191 * Returns -1 in case of error, 0 if the declaration is inproper and
3192 * 1 in case of success.
3193 */
3194static xmlSchemaTypePtr
3195xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003196 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003197{
3198 xmlSchemaTypePtr type, subtype, last = NULL;
3199 xmlNodePtr child = NULL;
3200 xmlChar name[30];
3201
3202 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3203 return (NULL);
3204
3205
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003206 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003207 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 if (type == NULL)
3209 return (NULL);
3210 type->node = node;
3211 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003212 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3214 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3215
3216 child = node->children;
3217 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003218 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003220 }
3221 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003222 (IS_SCHEMA(child, "group")) ||
3223 (IS_SCHEMA(child, "any")) ||
3224 (IS_SCHEMA(child, "choice")) ||
3225 (IS_SCHEMA(child, "sequence"))) {
3226 subtype = NULL;
3227 if (IS_SCHEMA(child, "element")) {
3228 subtype = (xmlSchemaTypePtr)
3229 xmlSchemaParseElement(ctxt, schema, child, 0);
3230 } else if (IS_SCHEMA(child, "group")) {
3231 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3232 } else if (IS_SCHEMA(child, "any")) {
3233 subtype = xmlSchemaParseAny(ctxt, schema, child);
3234 } else if (IS_SCHEMA(child, "choice")) {
3235 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3236 } else if (IS_SCHEMA(child, "sequence")) {
3237 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3238 }
3239 if (subtype != NULL) {
3240 if (last == NULL) {
3241 type->subtypes = subtype;
3242 last = subtype;
3243 } else {
3244 last->next = subtype;
3245 last = subtype;
3246 }
3247 last->next = NULL;
3248 }
3249 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003250 }
3251 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003252 xmlSchemaPErr2(ctxt, node, child,
3253 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3254 "Sequence %s has unexpected content\n", type->name,
3255 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003256 }
3257
3258 return (type);
3259}
3260
3261/**
3262 * xmlSchemaParseRestriction:
3263 * @ctxt: a schema validation context
3264 * @schema: the schema being built
3265 * @node: a subtree containing XML Schema informations
3266 * @simple: is that part of a simple type.
3267 *
3268 * parse a XML schema Restriction definition
3269 * *WARNING* this interface is highly subject to change
3270 *
3271 * Returns the type definition or NULL in case of error
3272 */
3273static xmlSchemaTypePtr
3274xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3275 xmlNodePtr node, int simple)
3276{
3277 xmlSchemaTypePtr type, subtype;
3278 xmlSchemaFacetPtr facet, lastfacet = NULL;
3279 xmlNodePtr child = NULL;
3280 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003281 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003282
3283 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3284 return (NULL);
3285
3286 oldcontainer = ctxt->container;
3287
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003288 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003289 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003290 if (type == NULL)
3291 return (NULL);
3292 type->node = node;
3293 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003294 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003295 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3296 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003297 xmlSchemaPErr2(ctxt, node, child,
3298 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3299 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003300 }
3301 ctxt->container = name;
3302
3303 child = node->children;
3304 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003305 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3306 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003307 }
3308 subtype = NULL;
3309
3310 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003311 subtype = (xmlSchemaTypePtr)
3312 xmlSchemaParseAll(ctxt, schema, child);
3313 child = child->next;
3314 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003315 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003316 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3317 child = child->next;
3318 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003319 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003320 subtype = (xmlSchemaTypePtr)
3321 xmlSchemaParseSequence(ctxt, schema, child);
3322 child = child->next;
3323 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003324 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003325 subtype = (xmlSchemaTypePtr)
3326 xmlSchemaParseGroup(ctxt, schema, child);
3327 child = child->next;
3328 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003329 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003330 if (IS_SCHEMA(child, "simpleType")) {
3331 subtype = (xmlSchemaTypePtr)
3332 xmlSchemaParseSimpleType(ctxt, schema, child);
3333 child = child->next;
3334 type->baseType = subtype;
3335 }
3336 /*
3337 * Facets
3338 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003339 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003340 (IS_SCHEMA(child, "minExclusive")) ||
3341 (IS_SCHEMA(child, "maxInclusive")) ||
3342 (IS_SCHEMA(child, "maxExclusive")) ||
3343 (IS_SCHEMA(child, "totalDigits")) ||
3344 (IS_SCHEMA(child, "fractionDigits")) ||
3345 (IS_SCHEMA(child, "pattern")) ||
3346 (IS_SCHEMA(child, "enumeration")) ||
3347 (IS_SCHEMA(child, "whiteSpace")) ||
3348 (IS_SCHEMA(child, "length")) ||
3349 (IS_SCHEMA(child, "maxLength")) ||
3350 (IS_SCHEMA(child, "minLength"))) {
3351 facet = xmlSchemaParseFacet(ctxt, schema, child);
3352 if (facet != NULL) {
3353 if (lastfacet == NULL) {
3354 type->facets = facet;
3355 lastfacet = facet;
3356 } else {
3357 lastfacet->next = facet;
3358 lastfacet = facet;
3359 }
3360 lastfacet->next = NULL;
3361 }
3362 child = child->next;
3363 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003364 }
3365 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3366 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003367 xmlSchemaPErr2(ctxt, node, child,
3368 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3369 "Restriction %s has unexpected content\n",
3370 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003371 }
3372 ctxt->container = oldcontainer;
3373 return (type);
3374}
3375
3376/**
3377 * xmlSchemaParseExtension:
3378 * @ctxt: a schema validation context
3379 * @schema: the schema being built
3380 * @node: a subtree containing XML Schema informations
3381 *
3382 * parse a XML schema Extension definition
3383 * *WARNING* this interface is highly subject to change
3384 *
3385 * Returns the type definition or NULL in case of error
3386 */
3387static xmlSchemaTypePtr
3388xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003389 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003390{
3391 xmlSchemaTypePtr type, subtype;
3392 xmlNodePtr child = NULL;
3393 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003394 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003395
3396 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3397 return (NULL);
3398
3399 oldcontainer = ctxt->container;
3400
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003402 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403 if (type == NULL)
3404 return (NULL);
3405 type->node = node;
3406 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003407 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 ctxt->container = name;
3409
3410 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3411 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3413 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003414 }
3415 child = node->children;
3416 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003417 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3418 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003419 }
3420 subtype = NULL;
3421
3422 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 subtype = xmlSchemaParseAll(ctxt, schema, child);
3424 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003425 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003426 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3427 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003428 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003429 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3430 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003431 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003432 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3433 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003434 }
3435 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003436 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003437 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3438 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003439 xmlSchemaPErr2(ctxt, node, child,
3440 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3441 "Extension %s has unexpected content\n", type->name,
3442 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003443 }
3444 ctxt->container = oldcontainer;
3445 return (type);
3446}
3447
3448/**
3449 * xmlSchemaParseSimpleContent:
3450 * @ctxt: a schema validation context
3451 * @schema: the schema being built
3452 * @node: a subtree containing XML Schema informations
3453 *
3454 * parse a XML schema SimpleContent definition
3455 * *WARNING* this interface is highly subject to change
3456 *
3457 * Returns the type definition or NULL in case of error
3458 */
3459static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003460xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3461 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003462{
3463 xmlSchemaTypePtr type, subtype;
3464 xmlNodePtr child = NULL;
3465 xmlChar name[30];
3466
3467 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3468 return (NULL);
3469
3470
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003471 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003472 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003473 if (type == NULL)
3474 return (NULL);
3475 type->node = node;
3476 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003477 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003478
3479 child = node->children;
3480 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003481 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3482 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003483 }
3484 subtype = NULL;
3485 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003486 subtype = (xmlSchemaTypePtr)
3487 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3488 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003489 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003490 subtype = (xmlSchemaTypePtr)
3491 xmlSchemaParseExtension(ctxt, schema, child);
3492 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003493 }
3494 type->subtypes = subtype;
3495 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003496 xmlSchemaPErr2(ctxt, node, child,
3497 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3498 "SimpleContent %s has unexpected content\n",
3499 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003500 }
3501 return (type);
3502}
3503
3504/**
3505 * xmlSchemaParseComplexContent:
3506 * @ctxt: a schema validation context
3507 * @schema: the schema being built
3508 * @node: a subtree containing XML Schema informations
3509 *
3510 * parse a XML schema ComplexContent definition
3511 * *WARNING* this interface is highly subject to change
3512 *
3513 * Returns the type definition or NULL in case of error
3514 */
3515static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003516xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3517 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003518{
3519 xmlSchemaTypePtr type, subtype;
3520 xmlNodePtr child = NULL;
3521 xmlChar name[30];
3522
3523 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3524 return (NULL);
3525
3526
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003527 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003528 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003529 if (type == NULL)
3530 return (NULL);
3531 type->node = node;
3532 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003533 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003534
3535 child = node->children;
3536 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003537 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3538 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003539 }
3540 subtype = NULL;
3541 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003542 subtype = (xmlSchemaTypePtr)
3543 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3544 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003545 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003546 subtype = (xmlSchemaTypePtr)
3547 xmlSchemaParseExtension(ctxt, schema, child);
3548 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003549 }
3550 type->subtypes = subtype;
3551 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003552 xmlSchemaPErr2(ctxt, node, child,
3553 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3554 "ComplexContent %s has unexpected content\n",
3555 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003556 }
3557 return (type);
3558}
3559
3560/**
3561 * xmlSchemaParseComplexType:
3562 * @ctxt: a schema validation context
3563 * @schema: the schema being built
3564 * @node: a subtree containing XML Schema informations
3565 *
3566 * parse a XML schema Complex Type definition
3567 * *WARNING* this interface is highly subject to change
3568 *
3569 * Returns the type definition or NULL in case of error
3570 */
3571static xmlSchemaTypePtr
3572xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3573 xmlNodePtr node)
3574{
3575 xmlSchemaTypePtr type, subtype;
3576 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003577 const xmlChar *name;
3578 const xmlChar *oldcontainer;
Daniel Veillard1aefc862004-03-04 11:40:48 +00003579 const xmlChar *mixed;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003580 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003581
3582 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3583 return (NULL);
3584
3585 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003586 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003587 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003588
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003589 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3590 name = (const xmlChar *)buf;
3591 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3592 } else {
3593 const xmlChar *local, *ns;
3594
3595 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3596 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003597 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003598 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 return (NULL);
3600 }
Daniel Veillard1aefc862004-03-04 11:40:48 +00003601
3602 mixed = xmlSchemaGetProp(ctxt, node, "mixed");
3603 if (mixed != NULL)
3604 type->flags |= XML_SCHEMAS_TYPE_MIXED;
3605
Daniel Veillard4255d502002-04-16 15:50:10 +00003606 type->node = node;
3607 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003608 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 ctxt->container = name;
3610
3611 child = node->children;
3612 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003613 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3614 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 }
3616 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003617 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3618 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003619 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003620 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3621 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003622 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003623 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003624
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003625 if (IS_SCHEMA(child, "all")) {
3626 subtype = xmlSchemaParseAll(ctxt, schema, child);
3627 child = child->next;
3628 } else if (IS_SCHEMA(child, "choice")) {
3629 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3630 child = child->next;
3631 } else if (IS_SCHEMA(child, "sequence")) {
3632 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3633 child = child->next;
3634 } else if (IS_SCHEMA(child, "group")) {
3635 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3636 child = child->next;
3637 }
3638 if (subtype != NULL)
3639 type->subtypes = subtype;
3640 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 }
3642 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003643 xmlSchemaPErr2(ctxt, node, child,
3644 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3645 "ComplexType %s has unexpected content\n",
3646 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003647 }
3648 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 return (type);
3650}
3651
Daniel Veillard4255d502002-04-16 15:50:10 +00003652/**
3653 * xmlSchemaParseSchema:
3654 * @ctxt: a schema validation context
3655 * @node: a subtree containing XML Schema informations
3656 *
3657 * parse a XML schema definition from a node set
3658 * *WARNING* this interface is highly subject to change
3659 *
3660 * Returns the internal XML Schema structure built from the resource or
3661 * NULL in case of error
3662 */
3663static xmlSchemaPtr
3664xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3665{
3666 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003668 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003669 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003670
3671 if ((ctxt == NULL) || (node == NULL))
3672 return (NULL);
3673
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003674 nberrors = ctxt->nberrors;
3675 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 if (IS_SCHEMA(node, "schema")) {
3677 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 if (schema == NULL)
3679 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003680 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3681 if (val != NULL) {
3682 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3683 } else {
3684 schema->targetNamespace = NULL;
3685 }
3686 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3687 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3688 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003689 if (val != NULL) {
3690 if (xmlStrEqual(val, BAD_CAST "qualified"))
3691 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3692 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3693 xmlSchemaPErr2(ctxt, node, child,
3694 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3695 "Invalid value %s for elementFormDefault\n",
3696 val, NULL);
3697 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003698 } else {
3699 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3700 }
3701 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003702 if (val != NULL) {
3703 if (xmlStrEqual(val, BAD_CAST "qualified"))
3704 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3705 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3706 xmlSchemaPErr2(ctxt, node, child,
3707 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3708 "Invalid value %s for attributeFormDefault\n",
3709 val, NULL);
3710 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003711 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003712
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003713 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
3714 } else {
3715 xmlDocPtr doc;
3716
3717 doc = node->doc;
3718
3719 if ((doc != NULL) && (doc->URL != NULL)) {
3720 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3721 XML_SCHEMAP_NOT_SCHEMA,
3722 "File %s is not a schemas", doc->URL, NULL);
3723 } else {
3724 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3725 XML_SCHEMAP_NOT_SCHEMA,
3726 "File is not a schemas", NULL, NULL);
3727 }
3728 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003729 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003730 if (ctxt->nberrors != 0) {
3731 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003732 xmlSchemaFree(schema);
3733 schema = NULL;
3734 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003735 }
3736 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003737#ifdef DEBUG
3738 if (schema == NULL)
3739 xmlGenericError(xmlGenericErrorContext,
3740 "xmlSchemaParse() failed\n");
3741#endif
3742
3743 return (schema);
3744}
3745
3746/************************************************************************
3747 * *
3748 * Validating using Schemas *
3749 * *
3750 ************************************************************************/
3751
3752/************************************************************************
3753 * *
3754 * Reading/Writing Schemas *
3755 * *
3756 ************************************************************************/
3757
3758/**
3759 * xmlSchemaNewParserCtxt:
3760 * @URL: the location of the schema
3761 *
3762 * Create an XML Schemas parse context for that file/resource expected
3763 * to contain an XML Schemas file.
3764 *
3765 * Returns the parser context or NULL in case of error
3766 */
3767xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003768xmlSchemaNewParserCtxt(const char *URL)
3769{
Daniel Veillard4255d502002-04-16 15:50:10 +00003770 xmlSchemaParserCtxtPtr ret;
3771
3772 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003773 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003774
3775 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3776 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3778 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003779 return (NULL);
3780 }
3781 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003782 ret->dict = xmlDictCreate();
3783 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003784 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003785 return (ret);
3786}
3787
3788/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003789 * xmlSchemaNewMemParserCtxt:
3790 * @buffer: a pointer to a char array containing the schemas
3791 * @size: the size of the array
3792 *
3793 * Create an XML Schemas parse context for that memory buffer expected
3794 * to contain an XML Schemas file.
3795 *
3796 * Returns the parser context or NULL in case of error
3797 */
3798xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003799xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3800{
Daniel Veillard6045c902002-10-09 21:13:59 +00003801 xmlSchemaParserCtxtPtr ret;
3802
3803 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003804 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003805
3806 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3807 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003808 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3809 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003810 return (NULL);
3811 }
3812 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3813 ret->buffer = buffer;
3814 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003815 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00003816 return (ret);
3817}
3818
3819/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003820 * xmlSchemaNewDocParserCtxt:
3821 * @doc: a preparsed document tree
3822 *
3823 * Create an XML Schemas parse context for that document.
3824 * NB. The document may be modified during the parsing process.
3825 *
3826 * Returns the parser context or NULL in case of error
3827 */
3828xmlSchemaParserCtxtPtr
3829xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3830{
3831 xmlSchemaParserCtxtPtr ret;
3832
3833 if (doc == NULL)
3834 return (NULL);
3835
3836 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3837 if (ret == NULL) {
3838 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3839 NULL);
3840 return (NULL);
3841 }
3842 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3843 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003844 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00003845 /* The application has responsibility for the document */
3846 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00003847
3848 return (ret);
3849}
3850
3851/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003852 * xmlSchemaFreeParserCtxt:
3853 * @ctxt: the schema parser context
3854 *
3855 * Free the resources associated to the schema parser context
3856 */
3857void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003858xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3859{
Daniel Veillard4255d502002-04-16 15:50:10 +00003860 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003861 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00003862 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003863 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003864 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003865 xmlFree(ctxt);
3866}
3867
3868/************************************************************************
3869 * *
3870 * Building the content models *
3871 * *
3872 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003873
Daniel Veillard4255d502002-04-16 15:50:10 +00003874/**
3875 * xmlSchemaBuildAContentModel:
3876 * @type: the schema type definition
3877 * @ctxt: the schema parser context
3878 * @name: the element name whose content is being built
3879 *
3880 * Generate the automata sequence needed for that type
3881 */
3882static void
3883xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003884 xmlSchemaParserCtxtPtr ctxt,
3885 const xmlChar * name)
3886{
Daniel Veillard4255d502002-04-16 15:50:10 +00003887 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003888 xmlGenericError(xmlGenericErrorContext,
3889 "Found unexpected type = NULL in %s content model\n",
3890 name);
3891 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003892 }
3893 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003894 case XML_SCHEMA_TYPE_ANY:
3895 /* TODO : handle the namespace too */
3896 /* TODO : make that a specific transition type */
3897 TODO ctxt->state =
3898 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3899 BAD_CAST "*", NULL);
3900 break;
3901 case XML_SCHEMA_TYPE_ELEMENT:{
3902 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003903
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003904 /* TODO : handle the namespace too */
3905 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003906
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003907 if (elem->maxOccurs >= UNBOUNDED) {
3908 if (elem->minOccurs > 1) {
3909 xmlAutomataStatePtr tmp;
3910 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003911
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003912 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3913 oldstate,
3914 NULL);
3915 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003916
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003917 counter = xmlAutomataNewCounter(ctxt->am,
3918 elem->minOccurs -
3919 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003920
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003921 if (elem->refDecl != NULL) {
3922 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3923 elem->refDecl,
3924 ctxt,
3925 elem->refDecl->
3926 name);
3927 } else {
3928 ctxt->state =
3929 xmlAutomataNewTransition(ctxt->am,
3930 ctxt->state, NULL,
3931 elem->name, type);
3932 }
3933 tmp = ctxt->state;
3934 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3935 counter);
3936 ctxt->state =
3937 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3938 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003939
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003940 } else {
3941 if (elem->refDecl != NULL) {
3942 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3943 elem->refDecl,
3944 ctxt,
3945 elem->refDecl->
3946 name);
3947 } else {
3948 ctxt->state =
3949 xmlAutomataNewTransition(ctxt->am,
3950 ctxt->state, NULL,
3951 elem->name, type);
3952 }
3953 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3954 oldstate);
3955 if (elem->minOccurs == 0) {
3956 /* basically an elem* */
3957 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3958 ctxt->state);
3959 }
3960 }
3961 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3962 xmlAutomataStatePtr tmp;
3963 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003964
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003965 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3966 oldstate, NULL);
3967 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003968
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003969 counter = xmlAutomataNewCounter(ctxt->am,
3970 elem->minOccurs - 1,
3971 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003972
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003973 if (elem->refDecl != NULL) {
3974 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3975 elem->refDecl, ctxt,
3976 elem->refDecl->name);
3977 } else {
3978 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3979 ctxt->state,
3980 NULL,
3981 elem->name,
3982 type);
3983 }
3984 tmp = ctxt->state;
3985 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3986 counter);
3987 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3988 NULL,
3989 counter);
3990 if (elem->minOccurs == 0) {
3991 /* basically an elem? */
3992 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3993 ctxt->state);
3994 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003995
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003996 } else {
3997 if (elem->refDecl != NULL) {
3998 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3999 elem->refDecl, ctxt,
4000 elem->refDecl->name);
4001 } else {
4002 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4003 ctxt->state,
4004 NULL,
4005 elem->name,
4006 type);
4007 }
4008 if (elem->minOccurs == 0) {
4009 /* basically an elem? */
4010 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4011 ctxt->state);
4012 }
4013 }
4014 break;
4015 }
4016 case XML_SCHEMA_TYPE_SEQUENCE:{
4017 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004018
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019 /*
4020 * If max and min occurances are default (1) then
4021 * simply iterate over the subtypes
4022 */
4023 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4024 subtypes = type->subtypes;
4025 while (subtypes != NULL) {
4026 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4027 subtypes = subtypes->next;
4028 }
4029 } else {
4030 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004031
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004032 if (type->maxOccurs >= UNBOUNDED) {
4033 if (type->minOccurs > 1) {
4034 xmlAutomataStatePtr tmp;
4035 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004036
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004037 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4038 oldstate,
4039 NULL);
4040 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004041
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004042 counter = xmlAutomataNewCounter(ctxt->am,
4043 type->
4044 minOccurs - 1,
4045 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004046
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004047 subtypes = type->subtypes;
4048 while (subtypes != NULL) {
4049 xmlSchemaBuildAContentModel(subtypes, ctxt,
4050 name);
4051 subtypes = subtypes->next;
4052 }
4053 tmp = ctxt->state;
4054 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4055 oldstate, counter);
4056 ctxt->state =
4057 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4058 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004059
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004060 } else {
4061 subtypes = type->subtypes;
4062 while (subtypes != NULL) {
4063 xmlSchemaBuildAContentModel(subtypes, ctxt,
4064 name);
4065 subtypes = subtypes->next;
4066 }
4067 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4068 oldstate);
4069 if (type->minOccurs == 0) {
4070 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4071 ctxt->state);
4072 }
4073 }
4074 } else if ((type->maxOccurs > 1)
4075 || (type->minOccurs > 1)) {
4076 xmlAutomataStatePtr tmp;
4077 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004078
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004079 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4080 oldstate,
4081 NULL);
4082 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004083
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004084 counter = xmlAutomataNewCounter(ctxt->am,
4085 type->minOccurs -
4086 1,
4087 type->maxOccurs -
4088 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004089
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004090 subtypes = type->subtypes;
4091 while (subtypes != NULL) {
4092 xmlSchemaBuildAContentModel(subtypes, ctxt,
4093 name);
4094 subtypes = subtypes->next;
4095 }
4096 tmp = ctxt->state;
4097 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4098 counter);
4099 ctxt->state =
4100 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4101 counter);
4102 if (type->minOccurs == 0) {
4103 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4104 ctxt->state);
4105 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004106
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004107 } else {
4108 subtypes = type->subtypes;
4109 while (subtypes != NULL) {
4110 xmlSchemaBuildAContentModel(subtypes, ctxt,
4111 name);
4112 subtypes = subtypes->next;
4113 }
4114 if (type->minOccurs == 0) {
4115 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4116 ctxt->state);
4117 }
4118 }
4119 }
4120 break;
4121 }
4122 case XML_SCHEMA_TYPE_CHOICE:{
4123 xmlSchemaTypePtr subtypes;
4124 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004125
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004126 start = ctxt->state;
4127 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004128
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004129 /*
4130 * iterate over the subtypes and remerge the end with an
4131 * epsilon transition
4132 */
4133 if (type->maxOccurs == 1) {
4134 subtypes = type->subtypes;
4135 while (subtypes != NULL) {
4136 ctxt->state = start;
4137 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4138 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4139 subtypes = subtypes->next;
4140 }
4141 } else {
4142 int counter;
4143 xmlAutomataStatePtr hop;
4144 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4145 UNBOUNDED : type->maxOccurs - 1;
4146 int minOccurs =
4147 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004148
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004149 /*
4150 * use a counter to keep track of the number of transtions
4151 * which went through the choice.
4152 */
4153 counter =
4154 xmlAutomataNewCounter(ctxt->am, minOccurs,
4155 maxOccurs);
4156 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004157
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004158 subtypes = type->subtypes;
4159 while (subtypes != NULL) {
4160 ctxt->state = start;
4161 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4162 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4163 subtypes = subtypes->next;
4164 }
4165 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4166 counter);
4167 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4168 counter);
4169 }
4170 if (type->minOccurs == 0) {
4171 xmlAutomataNewEpsilon(ctxt->am, start, end);
4172 }
4173 ctxt->state = end;
4174 break;
4175 }
4176 case XML_SCHEMA_TYPE_ALL:{
4177 xmlAutomataStatePtr start;
4178 xmlSchemaTypePtr subtypes;
4179 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4180 int lax;
4181
4182 subtypes = type->subtypes;
4183 if (subtypes == NULL)
4184 break;
4185 start = ctxt->state;
4186 while (subtypes != NULL) {
4187 ctxt->state = start;
4188 elem = (xmlSchemaElementPtr) subtypes;
4189
4190 /* TODO : handle the namespace too */
4191 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4192 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4193 ctxt->state, elem->name, 1,
4194 1, subtypes);
4195 } else {
4196 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4197 ctxt->state, elem->name,
4198 elem->minOccurs,
4199 elem->maxOccurs,
4200 subtypes);
4201 }
4202 subtypes = subtypes->next;
4203 }
4204 lax = type->minOccurs == 0;
4205 ctxt->state =
4206 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4207 lax);
4208 break;
4209 }
4210 case XML_SCHEMA_TYPE_RESTRICTION:
4211 if (type->subtypes != NULL)
4212 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4213 break;
4214 case XML_SCHEMA_TYPE_EXTENSION:
4215 if (type->baseType != NULL) {
4216 xmlSchemaTypePtr subtypes;
4217
4218 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4219 subtypes = type->subtypes;
4220 while (subtypes != NULL) {
4221 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4222 subtypes = subtypes->next;
4223 }
4224 } else if (type->subtypes != NULL)
4225 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4226 break;
4227 case XML_SCHEMA_TYPE_GROUP:
4228 if (type->subtypes == NULL) {
4229 }
4230 case XML_SCHEMA_TYPE_COMPLEX:
4231 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4232 if (type->subtypes != NULL)
4233 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4234 break;
4235 default:
4236 xmlGenericError(xmlGenericErrorContext,
4237 "Found unexpected type %d in %s content model\n",
4238 type->type, name);
4239 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004240 }
4241}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004242
Daniel Veillard4255d502002-04-16 15:50:10 +00004243/**
4244 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004245 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004246 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004247 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004249 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004250 */
4251static void
4252xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 xmlSchemaParserCtxtPtr ctxt,
4254 const xmlChar * name)
4255{
Daniel Veillard4255d502002-04-16 15:50:10 +00004256 xmlAutomataStatePtr start;
4257
Daniel Veillard4255d502002-04-16 15:50:10 +00004258 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004259 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004260 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004261 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4262 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004263 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004264 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004265 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004266 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4267 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004268 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004269
4270#ifdef DEBUG_CONTENT
4271 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004272 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004273#endif
4274
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 ctxt->am = xmlNewAutomata();
4276 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004277 xmlGenericError(xmlGenericErrorContext,
4278 "Cannot create automata for elem %s\n", name);
4279 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 }
4281 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4282 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4283 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004284 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004285 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004286 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4287 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004288 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004289 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4290 "Content model of %s is not determinist:\n", name,
4291 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004292 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004293#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 xmlGenericError(xmlGenericErrorContext,
4295 "Content model of %s:\n", name);
4296 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004297#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004298 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004299 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004300 xmlFreeAutomata(ctxt->am);
4301 ctxt->am = NULL;
4302}
4303
4304/**
4305 * xmlSchemaRefFixupCallback:
4306 * @elem: the schema element context
4307 * @ctxt: the schema parser context
4308 *
4309 * Free the resources associated to the schema parser context
4310 */
4311static void
4312xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004313 xmlSchemaParserCtxtPtr ctxt,
4314 const xmlChar * name,
4315 const xmlChar * context ATTRIBUTE_UNUSED,
4316 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004317{
4318 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004319 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004320 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004321 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004322
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004323 if (elem->subtypes != NULL) {
4324 xmlSchemaPErr(ctxt, elem->node,
4325 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4326 "Schemas: element %s have both ref and subtype\n",
4327 name, NULL);
4328 return;
4329 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004330 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004331
4332 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004333 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4334 "Schemas: element %s ref to %s not found\n",
4335 name, elem->ref);
4336 return;
4337 }
4338 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004339 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004340 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004341
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004342 if (elem->subtypes != NULL) {
4343 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4344 "Schemas: element %s have both type and subtype\n",
4345 name, NULL);
4346 return;
4347 }
4348 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4349 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004350
4351 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004352 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4353 "Schemas: element %s type %s not found\n", name,
4354 elem->namedType);
4355 return;
4356 }
4357 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 }
4359}
4360
4361/**
4362 * xmlSchemaTypeFixup:
4363 * @typeDecl: the schema type definition
4364 * @ctxt: the schema parser context
4365 *
4366 * Fixes the content model of the type.
4367 */
4368static void
4369xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004370 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004371{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004372 if (typeDecl == NULL)
4373 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004374 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004375 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004376 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004377 switch (typeDecl->type) {
4378 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4379 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4380 if (typeDecl->subtypes != NULL)
4381 typeDecl->contentType =
4382 typeDecl->subtypes->contentType;
4383 break;
4384 }
4385 case XML_SCHEMA_TYPE_RESTRICTION:{
4386 if (typeDecl->subtypes != NULL)
4387 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004388
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004389 if (typeDecl->base != NULL) {
4390 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004391
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004392 baseType =
4393 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4394 typeDecl->baseNs);
4395 if (baseType == NULL) {
4396 xmlSchemaPErr(ctxt, typeDecl->node,
4397 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004398 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004399 name, typeDecl->base);
4400 }
4401 typeDecl->baseType = baseType;
4402 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004403 if (typeDecl->subtypes == NULL)
4404 if (typeDecl->baseType != NULL)
4405 typeDecl->contentType =
4406 typeDecl->baseType->contentType;
4407 else
4408 /* 1.1.1 */
4409 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004410 else if ((typeDecl->subtypes->subtypes == NULL) &&
4411 ((typeDecl->subtypes->type ==
4412 XML_SCHEMA_TYPE_ALL)
4413 || (typeDecl->subtypes->type ==
4414 XML_SCHEMA_TYPE_SEQUENCE)))
4415 /* 1.1.2 */
4416 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4417 else if ((typeDecl->subtypes->type ==
4418 XML_SCHEMA_TYPE_CHOICE)
4419 && (typeDecl->subtypes->subtypes == NULL))
4420 /* 1.1.3 */
4421 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4422 else {
4423 /* 1.2 and 2.X are applied at the other layer */
4424 typeDecl->contentType =
4425 XML_SCHEMA_CONTENT_ELEMENTS;
4426 }
4427 break;
4428 }
4429 case XML_SCHEMA_TYPE_EXTENSION:{
4430 xmlSchemaContentType explicitContentType;
4431 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004432
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004433 if (typeDecl->base != NULL) {
4434 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004435
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004436 baseType =
4437 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4438 typeDecl->baseNs);
4439 if (baseType == NULL) {
4440 xmlSchemaPErr(ctxt, typeDecl->node,
4441 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004443 name, typeDecl->base);
4444 }
4445 typeDecl->baseType = baseType;
4446 }
4447 if (typeDecl->subtypes != NULL)
4448 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004449
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004450 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4451 if (typeDecl->subtypes == NULL)
4452 /* 1.1.1 */
4453 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4454 else if ((typeDecl->subtypes->subtypes == NULL) &&
4455 ((typeDecl->subtypes->type ==
4456 XML_SCHEMA_TYPE_ALL)
4457 || (typeDecl->subtypes->type ==
4458 XML_SCHEMA_TYPE_SEQUENCE)))
4459 /* 1.1.2 */
4460 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4461 else if ((typeDecl->subtypes->type ==
4462 XML_SCHEMA_TYPE_CHOICE)
4463 && (typeDecl->subtypes->subtypes == NULL))
4464 /* 1.1.3 */
4465 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004466
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004467 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4468 typeDecl->baseNs);
4469 if (base == NULL) {
4470 xmlSchemaPErr(ctxt, typeDecl->node,
4471 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4472 "Schemas: base type %s of type %s not found\n",
4473 typeDecl->base, name);
4474 return;
4475 }
4476 xmlSchemaTypeFixup(base, ctxt, NULL);
4477 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4478 /* 2.1 */
4479 typeDecl->contentType = base->contentType;
4480 } else if (base->contentType ==
4481 XML_SCHEMA_CONTENT_EMPTY) {
4482 /* 2.2 imbitable ! */
4483 typeDecl->contentType =
4484 XML_SCHEMA_CONTENT_ELEMENTS;
4485 } else {
4486 /* 2.3 imbitable pareil ! */
4487 typeDecl->contentType =
4488 XML_SCHEMA_CONTENT_ELEMENTS;
4489 }
4490 break;
4491 }
4492 case XML_SCHEMA_TYPE_COMPLEX:{
4493 if (typeDecl->subtypes == NULL) {
4494 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004495
4496 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4497 typeDecl->contentType =
4498 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004499 } else {
4500 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4501 typeDecl->contentType =
4502 XML_SCHEMA_CONTENT_MIXED;
4503 else {
4504 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4505 NULL);
4506 if (typeDecl->subtypes != NULL)
4507 typeDecl->contentType =
4508 typeDecl->subtypes->contentType;
4509 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004510 if (typeDecl->attributes == NULL)
4511 typeDecl->attributes =
4512 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004513 }
4514 break;
4515 }
4516 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4517 if (typeDecl->subtypes == NULL) {
4518 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004519 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4520 typeDecl->contentType =
4521 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004522 } else {
4523 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4524 typeDecl->contentType =
4525 XML_SCHEMA_CONTENT_MIXED;
4526 else {
4527 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4528 NULL);
4529 if (typeDecl->subtypes != NULL)
4530 typeDecl->contentType =
4531 typeDecl->subtypes->contentType;
4532 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004533 if (typeDecl->attributes == NULL)
4534 typeDecl->attributes =
4535 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004536 }
4537 break;
4538 }
4539 case XML_SCHEMA_TYPE_SEQUENCE:
4540 case XML_SCHEMA_TYPE_GROUP:
4541 case XML_SCHEMA_TYPE_ALL:
4542 case XML_SCHEMA_TYPE_CHOICE:
4543 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4544 break;
4545 case XML_SCHEMA_TYPE_BASIC:
4546 case XML_SCHEMA_TYPE_ANY:
4547 case XML_SCHEMA_TYPE_FACET:
4548 case XML_SCHEMA_TYPE_SIMPLE:
4549 case XML_SCHEMA_TYPE_UR:
4550 case XML_SCHEMA_TYPE_ELEMENT:
4551 case XML_SCHEMA_TYPE_ATTRIBUTE:
4552 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4553 case XML_SCHEMA_TYPE_NOTATION:
4554 case XML_SCHEMA_TYPE_LIST:
4555 case XML_SCHEMA_TYPE_UNION:
4556 case XML_SCHEMA_FACET_MININCLUSIVE:
4557 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4558 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4559 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4560 case XML_SCHEMA_FACET_TOTALDIGITS:
4561 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4562 case XML_SCHEMA_FACET_PATTERN:
4563 case XML_SCHEMA_FACET_ENUMERATION:
4564 case XML_SCHEMA_FACET_WHITESPACE:
4565 case XML_SCHEMA_FACET_LENGTH:
4566 case XML_SCHEMA_FACET_MAXLENGTH:
4567 case XML_SCHEMA_FACET_MINLENGTH:
4568 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004569 if (typeDecl->subtypes != NULL)
4570 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004571 break;
4572 }
4573 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004574#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004575 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004576 xmlGenericError(xmlGenericErrorContext,
4577 "Type of %s : %s:%d :", name,
4578 typeDecl->node->doc->URL,
4579 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004580 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004581 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004582 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004583 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004584 case XML_SCHEMA_CONTENT_SIMPLE:
4585 xmlGenericError(xmlGenericErrorContext, "simple\n");
4586 break;
4587 case XML_SCHEMA_CONTENT_ELEMENTS:
4588 xmlGenericError(xmlGenericErrorContext, "elements\n");
4589 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004590 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004591 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4592 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004593 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004594 xmlGenericError(xmlGenericErrorContext, "empty\n");
4595 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004596 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004597 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4598 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004599 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004600 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4601 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004602 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004603 xmlGenericError(xmlGenericErrorContext, "basic\n");
4604 break;
4605 default:
4606 xmlGenericError(xmlGenericErrorContext,
4607 "not registered !!!\n");
4608 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004609 }
4610#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004611}
4612
4613/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004614 * xmlSchemaCheckFacet:
4615 * @facet: the facet
4616 * @typeDecl: the schema type definition
4617 * @ctxt: the schema parser context or NULL
4618 * @name: name of the type
4619 *
4620 * Checks the default values types, especially for facets
4621 *
4622 * Returns 0 if okay or -1 in cae of error
4623 */
4624int
4625xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004626 xmlSchemaTypePtr typeDecl,
4627 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004628{
4629 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4630 int ret = 0;
4631
4632 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004633 nonNegativeIntegerType =
4634 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4635 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004636 }
4637 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004638 case XML_SCHEMA_FACET_MININCLUSIVE:
4639 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4640 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4641 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4642 /*
4643 * Okay we need to validate the value
4644 * at that point.
4645 */
4646 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004647
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004648 vctxt = xmlSchemaNewValidCtxt(NULL);
4649 if (vctxt == NULL)
4650 break;
4651 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4652 facet->value);
4653 facet->val = vctxt->value;
4654 vctxt->value = NULL;
4655 if (facet->val == NULL) {
4656 /* error code */
4657 if (ctxt != NULL) {
4658 xmlSchemaPErr(ctxt, facet->node,
4659 XML_SCHEMAP_INVALID_FACET,
4660 "Schemas: type %s facet value %s invalid\n",
4661 name, facet->value);
4662 }
4663 ret = -1;
4664 }
4665 xmlSchemaFreeValidCtxt(vctxt);
4666 break;
4667 }
4668 case XML_SCHEMA_FACET_ENUMERATION:{
4669 /*
4670 * Okay we need to validate the value
4671 * at that point.
4672 */
4673 xmlSchemaValidCtxtPtr vctxt;
4674 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004675
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004676 vctxt = xmlSchemaNewValidCtxt(NULL);
4677 if (vctxt == NULL)
4678 break;
4679 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4680 facet->value);
4681 if (tmp != 0) {
4682 if (ctxt != NULL) {
4683 xmlSchemaPErr(ctxt, facet->node,
4684 XML_SCHEMAP_INVALID_ENUM,
4685 "Schemas: type %s enumeration value %s invalid\n",
4686 name, facet->value);
4687 }
4688 ret = -1;
4689 }
4690 xmlSchemaFreeValidCtxt(vctxt);
4691 break;
4692 }
4693 case XML_SCHEMA_FACET_PATTERN:
4694 facet->regexp = xmlRegexpCompile(facet->value);
4695 if (facet->regexp == NULL) {
4696 xmlSchemaPErr(ctxt, typeDecl->node,
4697 XML_SCHEMAP_REGEXP_INVALID,
4698 "Schemas: type %s facet regexp %s invalid\n",
4699 name, facet->value);
4700 ret = -1;
4701 }
4702 break;
4703 case XML_SCHEMA_FACET_TOTALDIGITS:
4704 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4705 case XML_SCHEMA_FACET_LENGTH:
4706 case XML_SCHEMA_FACET_MAXLENGTH:
4707 case XML_SCHEMA_FACET_MINLENGTH:{
4708 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004709
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004710 tmp =
4711 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4712 facet->value,
4713 &facet->val);
4714 if (tmp != 0) {
4715 /* error code */
4716 if (ctxt != NULL) {
4717 xmlSchemaPErr(ctxt, facet->node,
4718 XML_SCHEMAP_INVALID_FACET_VALUE,
4719 "Schemas: type %s facet value %s invalid\n",
4720 name, facet->value);
4721 }
4722 ret = -1;
4723 }
4724 break;
4725 }
4726 case XML_SCHEMA_FACET_WHITESPACE:{
4727 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4728 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4729 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4730 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4731 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4732 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4733 } else {
4734 if (ctxt != NULL) {
4735 xmlSchemaPErr(ctxt, facet->node,
4736 XML_SCHEMAP_INVALID_WHITE_SPACE,
4737 "Schemas: type %s whiteSpace value %s invalid\n",
4738 name, facet->value);
4739 }
4740 ret = -1;
4741 }
4742 }
4743 default:
4744 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004745 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004746 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004747}
4748
4749/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004750 * xmlSchemaCheckDefaults:
4751 * @typeDecl: the schema type definition
4752 * @ctxt: the schema parser context
4753 *
4754 * Checks the default values types, especially for facets
4755 */
4756static void
4757xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004758 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004759{
Daniel Veillard4255d502002-04-16 15:50:10 +00004760 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004761 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004762 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004763 if (typeDecl->facets != NULL) {
4764 xmlSchemaFacetPtr facet = typeDecl->facets;
4765
4766 while (facet != NULL) {
4767 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4768 facet = facet->next;
4769 }
4770 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004771 }
4772}
4773
4774/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004775 * xmlSchemaAttrGrpFixup:
4776 * @attrgrpDecl: the schema attribute definition
4777 * @ctxt: the schema parser context
4778 * @name: the attribute name
4779 *
4780 * Fixes finish doing the computations on the attributes definitions
4781 */
4782static void
4783xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004784 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004785{
4786 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004787 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004788 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004790 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004791 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004792
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004793 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4794 attrgrpDecl->refNs);
4795 if (ref == NULL) {
4796 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4797 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4798 "Schemas: attribute group %s reference %s not found\n",
4799 name, attrgrpDecl->ref);
4800 return;
4801 }
4802 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4803 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004804 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004805 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4806 "Schemas: attribute %s has no attributes nor reference\n",
4807 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004808 }
4809}
4810
4811/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004812 * xmlSchemaAttrFixup:
4813 * @attrDecl: the schema attribute definition
4814 * @ctxt: the schema parser context
4815 * @name: the attribute name
4816 *
4817 * Fixes finish doing the computations on the attributes definitions
4818 */
4819static void
4820xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004821 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004822{
4823 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004825 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004826 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004827 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004829
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004830 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4831 attrDecl->typeNs);
4832 if (type == NULL) {
4833 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4834 "Schemas: attribute %s type %s not found\n",
4835 name, attrDecl->typeName);
4836 }
4837 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004838 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004839 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004840
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004841 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4842 attrDecl->refNs);
4843 if (ref == NULL) {
4844 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4845 "Schemas: attribute %s reference %s not found\n",
4846 name, attrDecl->ref);
4847 return;
4848 }
4849 xmlSchemaAttrFixup(ref, ctxt, NULL);
4850 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004851 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004852 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4853 "Schemas: attribute %s has no type nor reference\n",
4854 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 }
4856}
4857
4858/**
4859 * xmlSchemaParse:
4860 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004861 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004862 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004863 * XML Shema struture which can be used to validate instances.
4864 * *WARNING* this interface is highly subject to change
4865 *
4866 * Returns the internal XML Schema structure built from the resource or
4867 * NULL in case of error
4868 */
4869xmlSchemaPtr
4870xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4871{
4872 xmlSchemaPtr ret = NULL;
4873 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004874 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004875 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004876 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004877
4878 xmlSchemaInitTypes();
4879
Daniel Veillard6045c902002-10-09 21:13:59 +00004880 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004881 return (NULL);
4882
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004883 nberrors = ctxt->nberrors;
4884 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004885 ctxt->counter = 0;
4886 ctxt->container = NULL;
4887
4888 /*
4889 * First step is to parse the input document into an DOM/Infoset
4890 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004891 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004892 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4893 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004894 if (doc == NULL) {
4895 xmlSchemaPErr(ctxt, NULL,
4896 XML_SCHEMAP_FAILED_LOAD,
4897 "xmlSchemaParse: could not load %s\n",
4898 ctxt->URL, NULL);
4899 return (NULL);
4900 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004901 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004902 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4903 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 if (doc == NULL) {
4905 xmlSchemaPErr(ctxt, NULL,
4906 XML_SCHEMAP_FAILED_PARSE,
4907 "xmlSchemaParse: could not parse\n",
4908 NULL, NULL);
4909 return (NULL);
4910 }
4911 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00004912 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00004913 } else if (ctxt->doc != NULL) {
4914 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004915 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00004916 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004917 xmlSchemaPErr(ctxt, NULL,
4918 XML_SCHEMAP_NOTHING_TO_PARSE,
4919 "xmlSchemaParse: could not parse\n",
4920 NULL, NULL);
4921 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004922 }
4923
4924 /*
4925 * Then extract the root and Schema parse it
4926 */
4927 root = xmlDocGetRootElement(doc);
4928 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004929 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4930 XML_SCHEMAP_NOROOT,
4931 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00004932 if (!preserve) {
4933 xmlFreeDoc(doc);
4934 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004935 return (NULL);
4936 }
4937
4938 /*
4939 * Remove all the blank text nodes
4940 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004941 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00004942
4943 /*
4944 * Then do the parsing for good
4945 */
4946 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004947 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00004948 if (!preserve) {
4949 xmlFreeDoc(doc);
4950 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004951 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004952 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004953 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004954 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00004955
4956 /*
4957 * Then fix all the references.
4958 */
4959 ctxt->schema = ret;
4960 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004961 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004962
4963 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00004964 * Then fixup all attributes declarations
4965 */
4966 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4967
4968 /*
4969 * Then fixup all attributes group declarations
4970 */
4971 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4972 ctxt);
4973
4974 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00004975 * Then fixup all types properties
4976 */
4977 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4978
4979 /*
4980 * Then build the content model for all elements
4981 */
4982 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004983 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004984
4985 /*
4986 * Then check the defaults part of the type like facets values
4987 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004988 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4989 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004990
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004991 if (ctxt->nberrors != 0) {
4992 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004993 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004994 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004995 return (ret);
4996}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004997
Daniel Veillard4255d502002-04-16 15:50:10 +00004998/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004999 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00005000 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00005001 * @err: the error callback
5002 * @warn: the warning callback
5003 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00005004 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00005005 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00005006 */
5007void
5008xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005009 xmlSchemaValidityErrorFunc err,
5010 xmlSchemaValidityWarningFunc warn, void *ctx)
5011{
Daniel Veillard4255d502002-04-16 15:50:10 +00005012 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005013 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005014 ctxt->error = err;
5015 ctxt->warning = warn;
5016 ctxt->userData = ctx;
5017}
5018
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005019/**
5020 * xmlSchemaFacetTypeToString:
5021 * @type: the facet type
5022 *
5023 * Convert the xmlSchemaTypeType to a char string.
5024 *
5025 * Returns the char string representation of the facet type if the
5026 * type is a facet and an "Internal Error" string otherwise.
5027 */
5028static const char *
5029xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5030{
5031 switch (type) {
5032 case XML_SCHEMA_FACET_PATTERN:
5033 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005034 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005035 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005036 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005037 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005038 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005039 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005040 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005041 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005042 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005043 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005044 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005045 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005046 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005047 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005048 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005049 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005050 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005051 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005052 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005053 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005054 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005055 return ("fractionDigits");
5056 default:
5057 break;
5058 }
5059 return ("Internal Error");
5060}
5061
5062/**
5063 * xmlSchemaValidateFacets:
5064 * @ctxt: a schema validation context
5065 * @base: the base type
5066 * @facets: the list of facets to check
5067 * @value: the lexical repr of the value to validate
5068 * @val: the precomputed value
5069 *
5070 * Check a value against all facet conditions
5071 *
5072 * Returns 0 if the element is schemas valid, a positive error code
5073 * number otherwise and -1 in case of internal or API error.
5074 */
5075static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005076xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5077 xmlSchemaTypePtr base,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005078 xmlSchemaFacetPtr facets, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005079{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005080 int ret = 0;
5081 int tmp = 0;
5082 xmlSchemaTypeType type;
5083 xmlSchemaFacetPtr facet = facets;
5084
5085 while (facet != NULL) {
5086 type = facet->type;
5087 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005088 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005089
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005090 while (facet != NULL) {
5091 tmp =
5092 xmlSchemaValidateFacet(base, facet, value,
5093 ctxt->value);
5094 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005095 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005096 }
5097 facet = facet->next;
5098 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005099 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005100 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005101
5102 if (tmp != 0) {
5103 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005104 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 +00005105 }
5106 if (facet != NULL)
5107 facet = facet->next;
5108 }
5109 return (ret);
5110}
5111
Daniel Veillard4255d502002-04-16 15:50:10 +00005112/************************************************************************
5113 * *
5114 * Simple type validation *
5115 * *
5116 ************************************************************************/
5117
5118/**
5119 * xmlSchemaValidateSimpleValue:
5120 * @ctxt: a schema validation context
5121 * @type: the type declaration
5122 * @value: the value to validate
5123 *
5124 * Validate a value against a simple type
5125 *
5126 * Returns 0 if the value is valid, a positive error code
5127 * number otherwise and -1 in case of internal or API error.
5128 */
5129static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005130xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005131 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005132{
Daniel Veillard4255d502002-04-16 15:50:10 +00005133 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005134
Daniel Veillard4255d502002-04-16 15:50:10 +00005135 /*
5136 * First normalize the value accordingly to Schema Datatype
5137 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5138 */
5139 /*
5140 * Then check the normalized value against the lexical space of the
5141 * type.
5142 */
5143 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005144 if (ctxt->value != NULL) {
5145 xmlSchemaFreeValue(ctxt->value);
5146 ctxt->value = NULL;
5147 }
5148 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5149 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005150 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005151 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 +00005152 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005153 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005154 xmlSchemaTypePtr base;
5155 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005156
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005157 base = type->baseType;
5158 if (base != NULL) {
5159 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5160 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005161 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005162 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005163
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005164 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005165 * Do not validate facets or attributes when working on
5166 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167 */
5168 if (ctxt->schema != NULL) {
5169 if (ret == 0) {
5170 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005171 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005172 }
5173 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005174 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005176
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 base = type->subtypes;
5178 if (base != NULL) {
5179 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5180 } else {
5181 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005182 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005183 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005184 const xmlChar *cur, *end;
5185 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005186 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005187
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005188 base = type->subtypes;
5189 if (base == NULL) {
5190 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5191 "Internal: List type %s has no base type\n",
5192 type->name, NULL);
5193 return (-1);
5194 }
5195 cur = value;
5196 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005197 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005198 cur++;
5199 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005200 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005201 end++;
5202 if (end == cur)
5203 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005204 tmp = xmlStrndup(cur, end - cur);
5205 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
5206 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005207 if (ret2 != 0)
5208 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 cur = end;
5210 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005211 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005212 TODO
5213 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005214 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005215}
5216
5217/************************************************************************
5218 * *
5219 * DOM Validation code *
5220 * *
5221 ************************************************************************/
5222
5223static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005224 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005225static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005226 xmlNodePtr elem,
5227 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005228static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005229 xmlNodePtr elem,
5230 xmlSchemaElementPtr elemDecl,
5231 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005232
5233/**
5234 * xmlSchemaRegisterAttributes:
5235 * @ctxt: a schema validation context
5236 * @attrs: a list of attributes
5237 *
5238 * Register the list of attributes as the set to be validated on that element
5239 *
5240 * Returns -1 in case of error, 0 otherwise
5241 */
5242static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005243xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5244{
Daniel Veillard4255d502002-04-16 15:50:10 +00005245 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005246 if ((attrs->ns != NULL) &&
5247 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5248 attrs = attrs->next;
5249 continue;
5250 }
5251 if (ctxt->attrNr >= ctxt->attrMax) {
5252 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005253
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005254 ctxt->attrMax *= 2;
5255 tmp = (xmlSchemaAttrStatePtr)
5256 xmlRealloc(ctxt->attr, ctxt->attrMax *
5257 sizeof(xmlSchemaAttrState));
5258 if (tmp == NULL) {
5259 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5260 ctxt->attrMax /= 2;
5261 return (-1);
5262 }
5263 ctxt->attr = tmp;
5264 }
5265 ctxt->attr[ctxt->attrNr].attr = attrs;
5266 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5267 ctxt->attrNr++;
5268 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005269 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005270 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005271}
5272
5273/**
5274 * xmlSchemaCheckAttributes:
5275 * @ctxt: a schema validation context
5276 * @node: the node carrying it.
5277 *
5278 * Check that the registered set of attributes on the current node
5279 * has been properly validated.
5280 *
5281 * Returns 0 if validity constraints are met, 1 otherwise.
5282 */
5283static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005284xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5285{
Daniel Veillard4255d502002-04-16 15:50:10 +00005286 int ret = 0;
5287 int i;
5288
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005289 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5290 if (ctxt->attr[i].attr == NULL)
5291 break;
5292 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5293 ret = 1;
5294 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5295 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005296 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005297 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005298}
5299
5300/**
5301 * xmlSchemaValidateSimpleContent:
5302 * @ctxt: a schema validation context
5303 * @elem: an element
5304 * @type: the type declaration
5305 *
5306 * Validate the content of an element expected to be a simple type
5307 *
5308 * Returns 0 if the element is schemas valid, a positive error code
5309 * number otherwise and -1 in case of internal or API error.
5310 */
5311static int
5312xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005313 xmlNodePtr node ATTRIBUTE_UNUSED)
5314{
Daniel Veillard4255d502002-04-16 15:50:10 +00005315 xmlNodePtr child;
5316 xmlSchemaTypePtr type, base;
5317 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005318 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005319
5320 child = ctxt->node;
5321 type = ctxt->type;
5322
5323 /*
5324 * Validation Rule: Element Locally Valid (Type): 3.1.3
5325 */
5326 value = xmlNodeGetContent(child);
5327 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5328 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005329 case XML_SCHEMA_TYPE_RESTRICTION:{
5330 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005331
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005332 base = type->baseType;
5333 if (base != NULL) {
5334 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5335 } else {
5336 TODO}
5337 if (ret == 0) {
5338 facet = type->facets;
5339 ret =
5340 xmlSchemaValidateFacets(ctxt, base, facet, value);
5341 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005342 if ((ret == 0) && (type->attributes != NULL)) {
5343 ret = xmlSchemaValidateAttributes(ctxt, node,
5344 type->attributes);
5345 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005346 break;
5347 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005348 case XML_SCHEMA_TYPE_EXTENSION:{
5349 TODO
5350 break;
5351 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005352 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005353 TODO
5354 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005355 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005357
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005358 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005359}
5360
5361/**
5362 * xmlSchemaValidateCheckNodeList
5363 * @nodelist: the list of nodes
5364 *
5365 * Check the node list is only made of text nodes and entities pointing
5366 * to text nodes
5367 *
5368 * Returns 1 if true, 0 if false and -1 in case of error
5369 */
5370static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005371xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5372{
Daniel Veillard4255d502002-04-16 15:50:10 +00005373 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005374 if (nodelist->type == XML_ENTITY_REF_NODE) {
5375 TODO /* implement recursion in the entity content */
5376 }
5377 if ((nodelist->type != XML_TEXT_NODE) &&
5378 (nodelist->type != XML_COMMENT_NODE) &&
5379 (nodelist->type != XML_PI_NODE) &&
5380 (nodelist->type != XML_PI_NODE)) {
5381 return (0);
5382 }
5383 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005384 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005385 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005386}
5387
5388/**
5389 * xmlSchemaSkipIgnored:
5390 * @ctxt: a schema validation context
5391 * @type: the current type context
5392 * @node: the top node.
5393 *
5394 * Skip ignorable nodes in that context
5395 *
5396 * Returns the new sibling
5397 * number otherwise and -1 in case of internal or API error.
5398 */
5399static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005400xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005401 xmlSchemaTypePtr type, xmlNodePtr node)
5402{
Daniel Veillard4255d502002-04-16 15:50:10 +00005403 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005404
Daniel Veillard4255d502002-04-16 15:50:10 +00005405 /*
5406 * TODO complete and handle entities
5407 */
5408 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005409 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005410 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005411 ((node->type == XML_COMMENT_NODE) ||
5412 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5413 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5414 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5415 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005416 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005418}
5419
5420/**
5421 * xmlSchemaValidateCallback:
5422 * @ctxt: a schema validation context
5423 * @name: the name of the element detected (might be NULL)
5424 * @type: the type
5425 *
5426 * A transition has been made in the automata associated to an element
5427 * content model
5428 */
5429static void
5430xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005431 const xmlChar * name ATTRIBUTE_UNUSED,
5432 xmlSchemaTypePtr type, xmlNodePtr node)
5433{
Daniel Veillard4255d502002-04-16 15:50:10 +00005434 xmlSchemaTypePtr oldtype = ctxt->type;
5435 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005436
Daniel Veillard4255d502002-04-16 15:50:10 +00005437#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005438 xmlGenericError(xmlGenericErrorContext,
5439 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005440 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005441#endif
5442 ctxt->type = type;
5443 ctxt->node = node;
5444 xmlSchemaValidateContent(ctxt, node);
5445 ctxt->type = oldtype;
5446 ctxt->node = oldnode;
5447}
5448
5449
5450#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005451
Daniel Veillard4255d502002-04-16 15:50:10 +00005452/**
5453 * xmlSchemaValidateSimpleRestrictionType:
5454 * @ctxt: a schema validation context
5455 * @node: the top node.
5456 *
5457 * Validate the content of a restriction type.
5458 *
5459 * Returns 0 if the element is schemas valid, a positive error code
5460 * number otherwise and -1 in case of internal or API error.
5461 */
5462static int
5463xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5464 xmlNodePtr node)
5465{
5466 xmlNodePtr child;
5467 xmlSchemaTypePtr type;
5468 int ret;
5469
5470 child = ctxt->node;
5471 type = ctxt->type;
5472
5473 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005474 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005475 return (-1);
5476 }
5477 /*
5478 * Only text and text based entities references shall be found there
5479 */
5480 ret = xmlSchemaValidateCheckNodeList(child);
5481 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005482 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005483 return (-1);
5484 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005485 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 +00005486 return (-1);
5487 }
5488 ctxt->type = type->subtypes;
5489 xmlSchemaValidateContent(ctxt, node);
5490 ctxt->type = type;
5491 return (ret);
5492}
5493#endif
5494
5495/**
5496 * xmlSchemaValidateSimpleType:
5497 * @ctxt: a schema validation context
5498 * @node: the top node.
5499 *
5500 * Validate the content of an simple type.
5501 *
5502 * Returns 0 if the element is schemas valid, a positive error code
5503 * number otherwise and -1 in case of internal or API error.
5504 */
5505static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005506xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5507{
Daniel Veillard4255d502002-04-16 15:50:10 +00005508 xmlNodePtr child;
5509 xmlSchemaTypePtr type;
5510 xmlAttrPtr attr;
5511 int ret;
5512
5513 child = ctxt->node;
5514 type = ctxt->type;
5515
5516 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005517 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5518 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005519 }
5520 /*
5521 * Only text and text based entities references shall be found there
5522 */
5523 ret = xmlSchemaValidateCheckNodeList(child);
5524 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005525 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5526 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005527 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005528 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5529 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005530 }
5531 /*
5532 * Validation Rule: Element Locally Valid (Type): 3.1.1
5533 */
5534 attr = node->properties;
5535 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005536 if ((attr->ns == NULL) ||
5537 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5538 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5539 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5540 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5541 (!xmlStrEqual
5542 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5543 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5544 return (ctxt->err);
5545 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005546 }
5547
5548 ctxt->type = type->subtypes;
5549 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5550 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005551 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005552}
5553
5554/**
5555 * xmlSchemaValidateElementType:
5556 * @ctxt: a schema validation context
5557 * @node: the top node.
5558 *
5559 * Validate the content of an element type.
5560 * Validation Rule: Element Locally Valid (Complex Type)
5561 *
5562 * Returns 0 if the element is schemas valid, a positive error code
5563 * number otherwise and -1 in case of internal or API error.
5564 */
5565static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005566xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5567{
Daniel Veillard4255d502002-04-16 15:50:10 +00005568 xmlNodePtr child;
5569 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005570 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005571 xmlSchemaElementPtr decl;
5572 int ret, attrBase;
5573
5574 oldregexp = ctxt->regexp;
5575
5576 child = ctxt->node;
5577 type = ctxt->type;
5578
5579 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005580 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5581 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005582 }
5583 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005584 if (type->minOccurs > 0) {
5585 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5586 }
5587 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005588 }
5589
5590 /*
5591 * Verify the element matches
5592 */
5593 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005594 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5595 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005596 }
5597 /*
5598 * Verify the attributes
5599 */
5600 attrBase = ctxt->attrBase;
5601 ctxt->attrBase = ctxt->attrNr;
5602 xmlSchemaRegisterAttributes(ctxt, child->properties);
5603 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5604 /*
5605 * Verify the element content recursively
5606 */
5607 decl = (xmlSchemaElementPtr) type;
5608 oldregexp = ctxt->regexp;
5609 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005610 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5611 (xmlRegExecCallbacks)
5612 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005613#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005614 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005615#endif
5616 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005617 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5618 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005619
5620 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005621 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005622#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005623 xmlGenericError(xmlGenericErrorContext,
5624 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005625#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 if (ret == 0) {
5627 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5628 } else if (ret < 0) {
5629 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005630#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005631 } else {
5632 xmlGenericError(xmlGenericErrorContext,
5633 "Element %s content check succeeded\n",
5634 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005635
5636#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005637 }
5638 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005639 }
5640 /*
5641 * Verify that all attributes were Schemas-validated
5642 */
5643 xmlSchemaCheckAttributes(ctxt, node);
5644 ctxt->attrNr = ctxt->attrBase;
5645 ctxt->attrBase = attrBase;
5646
5647 ctxt->regexp = oldregexp;
5648
5649 ctxt->node = child;
5650 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005651 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005652}
5653
5654/**
5655 * xmlSchemaValidateBasicType:
5656 * @ctxt: a schema validation context
5657 * @node: the top node.
5658 *
5659 * Validate the content of an element expected to be a basic type type
5660 *
5661 * Returns 0 if the element is schemas valid, a positive error code
5662 * number otherwise and -1 in case of internal or API error.
5663 */
5664static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005665xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5666{
Daniel Veillard4255d502002-04-16 15:50:10 +00005667 int ret;
5668 xmlNodePtr child, cur;
5669 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005670 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005671
5672 child = ctxt->node;
5673 type = ctxt->type;
5674
5675 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005676 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5677 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005678 }
5679 /*
5680 * First check the content model of the node.
5681 */
5682 cur = child;
5683 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005684 switch (cur->type) {
5685 case XML_TEXT_NODE:
5686 case XML_CDATA_SECTION_NODE:
5687 case XML_PI_NODE:
5688 case XML_COMMENT_NODE:
5689 case XML_XINCLUDE_START:
5690 case XML_XINCLUDE_END:
5691 break;
5692 case XML_ENTITY_REF_NODE:
5693 case XML_ENTITY_NODE:
5694 TODO break;
5695 case XML_ELEMENT_NODE:
5696 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5697 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005698 case XML_ATTRIBUTE_NODE:
5699 case XML_DOCUMENT_NODE:
5700 case XML_DOCUMENT_TYPE_NODE:
5701 case XML_DOCUMENT_FRAG_NODE:
5702 case XML_NOTATION_NODE:
5703 case XML_HTML_DOCUMENT_NODE:
5704 case XML_DTD_NODE:
5705 case XML_ELEMENT_DECL:
5706 case XML_ATTRIBUTE_DECL:
5707 case XML_ENTITY_DECL:
5708 case XML_NAMESPACE_DECL:
5709#ifdef LIBXML_DOCB_ENABLED
5710 case XML_DOCB_DOCUMENT_NODE:
5711#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005712 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5713 return (ctxt->err);
5714 }
5715 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005716 }
5717 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005718 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005719 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005720 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005721
5722 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005723 xmlSchemaFreeValue(ctxt->value);
5724 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005725 }
5726 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5727 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005728 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005729 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005730 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 +00005731 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005732 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005733}
5734
5735/**
5736 * xmlSchemaValidateComplexType:
5737 * @ctxt: a schema validation context
5738 * @node: the top node.
5739 *
5740 * Validate the content of an element expected to be a complex type type
5741 * xmlschema-1.html#cvc-complex-type
5742 * Validation Rule: Element Locally Valid (Complex Type)
5743 *
5744 * Returns 0 if the element is schemas valid, a positive error code
5745 * number otherwise and -1 in case of internal or API error.
5746 */
5747static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005748xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5749{
Daniel Veillard4255d502002-04-16 15:50:10 +00005750 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005751 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005752 int ret;
5753
5754 child = ctxt->node;
5755 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005756 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005757
Daniel Veillard4255d502002-04-16 15:50:10 +00005758 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005759 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005760 if (type->baseType != NULL) {
5761 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005762 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5763 }
5764 if (type->attributes != NULL) {
5765 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5766 }
5767 subtype = type->subtypes;
5768 while (subtype != NULL) {
5769 ctxt->type = subtype;
5770 xmlSchemaValidateComplexType(ctxt, node);
5771 subtype = subtype->next;
5772 }
5773 break;
5774 case XML_SCHEMA_CONTENT_ELEMENTS:
5775 case XML_SCHEMA_CONTENT_MIXED:
5776 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5777 /*
5778 * Skip ignorable nodes in that context
5779 */
5780 child = xmlSchemaSkipIgnored(ctxt, type, child);
5781 while (child != NULL) {
5782 if (child->type == XML_ELEMENT_NODE) {
5783 ret = xmlRegExecPushString(ctxt->regexp,
5784 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005785#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005786 if (ret < 0)
5787 xmlGenericError(xmlGenericErrorContext,
5788 " --> %s Error\n", child->name);
5789 else
5790 xmlGenericError(xmlGenericErrorContext,
5791 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005792#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005793 }
5794 child = child->next;
5795 /*
5796 * Skip ignorable nodes in that context
5797 */
5798 child = xmlSchemaSkipIgnored(ctxt, type, child);
5799 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005800 if (type->attributes != NULL) {
5801 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5802 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 break;
5804 case XML_SCHEMA_CONTENT_BASIC:{
5805 if (type->subtypes != NULL) {
5806 ctxt->type = type->subtypes;
5807 xmlSchemaValidateComplexType(ctxt, node);
5808 }
5809 if (type->baseType != NULL) {
5810 ctxt->type = type->baseType;
5811 xmlSchemaValidateBasicType(ctxt, node);
5812 }
5813 if (type->attributes != NULL) {
5814 xmlSchemaValidateAttributes(ctxt, node,
5815 type->attributes);
5816 }
5817 ctxt->type = type;
5818 break;
5819 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005820 case XML_SCHEMA_CONTENT_SIMPLE:{
5821 if (type->subtypes != NULL) {
5822 ctxt->type = type->subtypes;
5823 xmlSchemaValidateComplexType(ctxt, node);
5824 }
5825 if (type->baseType != NULL) {
5826 ctxt->type = type->baseType;
5827 xmlSchemaValidateComplexType(ctxt, node);
5828 }
5829 if (type->attributes != NULL) {
5830 xmlSchemaValidateAttributes(ctxt, node,
5831 type->attributes);
5832 }
5833 ctxt->type = type;
5834 break;
5835 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005836 default:
5837 TODO xmlGenericError(xmlGenericErrorContext,
5838 "unimplemented content type %d\n",
5839 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005841 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005842}
5843
5844/**
5845 * xmlSchemaValidateContent:
5846 * @ctxt: a schema validation context
5847 * @elem: an element
5848 * @type: the type declaration
5849 *
5850 * Validate the content of an element against the type.
5851 *
5852 * Returns 0 if the element is schemas valid, a positive error code
5853 * number otherwise and -1 in case of internal or API error.
5854 */
5855static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005856xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5857{
Daniel Veillard4255d502002-04-16 15:50:10 +00005858 xmlNodePtr child;
5859 xmlSchemaTypePtr type;
5860
5861 child = ctxt->node;
5862 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005863 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005864
Daniel Veillarde19fc232002-04-22 16:01:24 +00005865 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005866 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005867
Daniel Veillard4255d502002-04-16 15:50:10 +00005868 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005869 case XML_SCHEMA_TYPE_ANY:
5870 /* Any type will do it, fine */
5871 TODO /* handle recursivity */
5872 break;
5873 case XML_SCHEMA_TYPE_COMPLEX:
5874 xmlSchemaValidateComplexType(ctxt, node);
5875 break;
5876 case XML_SCHEMA_TYPE_ELEMENT:{
5877 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5878
5879 /*
5880 * Handle element reference here
5881 */
5882 if (decl->ref != NULL) {
5883 if (decl->refDecl == NULL) {
5884 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5885 return (-1);
5886 }
5887 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5888 decl = decl->refDecl;
5889 }
5890 xmlSchemaValidateElementType(ctxt, node);
5891 ctxt->type = type;
5892 break;
5893 }
5894 case XML_SCHEMA_TYPE_BASIC:
5895 xmlSchemaValidateBasicType(ctxt, node);
5896 break;
5897 case XML_SCHEMA_TYPE_FACET:
5898 TODO break;
5899 case XML_SCHEMA_TYPE_SIMPLE:
5900 xmlSchemaValidateSimpleType(ctxt, node);
5901 break;
5902 case XML_SCHEMA_TYPE_SEQUENCE:
5903 TODO break;
5904 case XML_SCHEMA_TYPE_CHOICE:
5905 TODO break;
5906 case XML_SCHEMA_TYPE_ALL:
5907 TODO break;
5908 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5909 TODO break;
5910 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5911 TODO break;
5912 case XML_SCHEMA_TYPE_UR:
5913 TODO break;
5914 case XML_SCHEMA_TYPE_RESTRICTION:
5915 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5916 TODO break;
5917 case XML_SCHEMA_TYPE_EXTENSION:
5918 TODO break;
5919 case XML_SCHEMA_TYPE_ATTRIBUTE:
5920 TODO break;
5921 case XML_SCHEMA_TYPE_GROUP:
5922 TODO break;
5923 case XML_SCHEMA_TYPE_NOTATION:
5924 TODO break;
5925 case XML_SCHEMA_TYPE_LIST:
5926 TODO break;
5927 case XML_SCHEMA_TYPE_UNION:
5928 TODO break;
5929 case XML_SCHEMA_FACET_MININCLUSIVE:
5930 TODO break;
5931 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5932 TODO break;
5933 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5934 TODO break;
5935 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5936 TODO break;
5937 case XML_SCHEMA_FACET_TOTALDIGITS:
5938 TODO break;
5939 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5940 TODO break;
5941 case XML_SCHEMA_FACET_PATTERN:
5942 TODO break;
5943 case XML_SCHEMA_FACET_ENUMERATION:
5944 TODO break;
5945 case XML_SCHEMA_FACET_WHITESPACE:
5946 TODO break;
5947 case XML_SCHEMA_FACET_LENGTH:
5948 TODO break;
5949 case XML_SCHEMA_FACET_MAXLENGTH:
5950 TODO break;
5951 case XML_SCHEMA_FACET_MINLENGTH:
5952 TODO break;
5953 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5954 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005955 }
5956 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5957
5958 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005959 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005960 ctxt->node = ctxt->node->next;
5961 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005962 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005963}
5964
5965/**
5966 * xmlSchemaValidateType:
5967 * @ctxt: a schema validation context
5968 * @elem: an element
5969 * @type: the list of type declarations
5970 *
5971 * Validate the content of an element against the types.
5972 *
5973 * Returns 0 if the element is schemas valid, a positive error code
5974 * number otherwise and -1 in case of internal or API error.
5975 */
5976static int
5977xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005978 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5979{
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 xmlChar *nil;
5981
Daniel Veillard2db8c122003-07-08 12:16:59 +00005982 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005983 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005984
Daniel Veillard4255d502002-04-16 15:50:10 +00005985 /*
5986 * 3.3.4 : 2
5987 */
5988 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005989 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5990 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005991 }
5992 /*
5993 * 3.3.4: 3
5994 */
5995 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5996 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005997 /* 3.3.4: 3.2 */
5998 if (xmlStrEqual(nil, BAD_CAST "true")) {
5999 if (elem->children != NULL) {
6000 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
6001 return (ctxt->err);
6002 }
6003 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
6004 (elemDecl->value != NULL)) {
6005 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
6006 return (ctxt->err);
6007 }
6008 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006009 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006010 /* 3.3.4: 3.1 */
6011 if (nil != NULL) {
6012 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
6013 xmlFree(nil);
6014 return (ctxt->err);
6015 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006016 }
6017
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006018 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006019
6020 ctxt->type = elemDecl->subtypes;
6021 ctxt->node = elem->children;
6022 xmlSchemaValidateContent(ctxt, elem);
6023 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006024
6025 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006026}
6027
6028
6029/**
6030 * xmlSchemaValidateAttributes:
6031 * @ctxt: a schema validation context
6032 * @elem: an element
6033 * @attributes: the list of attribute declarations
6034 *
6035 * Validate the attributes of an element.
6036 *
6037 * Returns 0 if the element is schemas valid, a positive error code
6038 * number otherwise and -1 in case of internal or API error.
6039 */
6040static int
6041xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006042 xmlSchemaAttributePtr attributes)
6043{
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 int i, ret;
6045 xmlAttrPtr attr;
6046 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006047 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006048
6049 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006050 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006052 /*
6053 * Handle attribute groups
6054 */
6055 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6056 group = (xmlSchemaAttributeGroupPtr) attributes;
6057 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6058 attributes = group->next;
6059 continue;
6060 }
6061 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6062 attr = ctxt->attr[i].attr;
6063 if (attr == NULL)
6064 continue;
6065 if (attributes->ref != NULL) {
6066 if (!xmlStrEqual(attr->name, attributes->ref))
6067 continue;
6068 if (attr->ns != NULL) {
6069 if ((attributes->refNs == NULL) ||
6070 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6071 continue;
6072 } else if (attributes->refNs != NULL) {
6073 continue;
6074 }
6075 } else {
6076 if (!xmlStrEqual(attr->name, attributes->name))
6077 continue;
6078 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006079 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006080 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006081 if (attr->ns == NULL) {
6082 /*
6083 * accept an unqualified attribute only if the declaration
6084 * is unqualified or if the schemas allowed it.
6085 */
6086 if ((attributes->targetNamespace != NULL) &&
6087 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6088 continue;
6089 } else {
6090 if (attributes->targetNamespace == NULL)
6091 continue;
6092 if (!xmlStrEqual(attributes->targetNamespace,
6093 attr->ns->href))
6094 continue;
6095 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006096 }
6097 ctxt->cur = (xmlNodePtr) attributes;
6098 if (attributes->subtypes == NULL) {
6099 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6100 continue;
6101 }
6102 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6103 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6104 value);
6105 if (ret != 0) {
6106 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6107 } else {
6108 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6109 }
6110 if (value != NULL) {
6111 xmlFree(value);
6112 }
6113 }
6114 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006115 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006116 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006117}
6118
6119/**
6120 * xmlSchemaValidateElement:
6121 * @ctxt: a schema validation context
6122 * @elem: an element
6123 *
6124 * Validate an element in a tree
6125 *
6126 * Returns 0 if the element is schemas valid, a positive error code
6127 * number otherwise and -1 in case of internal or API error.
6128 */
6129static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006130xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6131{
Daniel Veillard4255d502002-04-16 15:50:10 +00006132 xmlSchemaElementPtr elemDecl;
6133 int ret, attrBase;
6134
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006135 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006136 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6137 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006138 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006139 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6140 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006141 }
6142 /*
6143 * special case whe elementFormDefault is unqualified for top-level elem.
6144 */
6145 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6146 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6147 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6148 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6149 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6150 elem->name, NULL, NULL);
6151 }
6152
Daniel Veillard4255d502002-04-16 15:50:10 +00006153 /*
6154 * 3.3.4 : 1
6155 */
6156 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006157 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6158 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 }
6160 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006161 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6162 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006163 }
6164 /*
6165 * Verify the attributes
6166 */
6167 attrBase = ctxt->attrBase;
6168 ctxt->attrBase = ctxt->attrNr;
6169 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6170 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6171 /*
6172 * Verify the element content recursively
6173 */
6174 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006175 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6176 (xmlRegExecCallbacks)
6177 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006178#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006179 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006180#endif
6181 }
6182 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006183 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006184 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006185#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006186 xmlGenericError(xmlGenericErrorContext,
6187 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006188#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189 if (ret == 0) {
6190 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6191 } else if (ret < 0) {
6192 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006193#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006194 } else {
6195 xmlGenericError(xmlGenericErrorContext,
6196 "Element %s content check succeeded\n",
6197 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006198
6199#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006200 }
6201 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 }
6203 /*
6204 * Verify that all attributes were Schemas-validated
6205 */
6206 xmlSchemaCheckAttributes(ctxt, elem);
6207 ctxt->attrNr = ctxt->attrBase;
6208 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006209
6210 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006211}
6212
6213/**
6214 * xmlSchemaValidateDocument:
6215 * @ctxt: a schema validation context
6216 * @doc: a parsed document tree
6217 *
6218 * Validate a document tree in memory.
6219 *
6220 * Returns 0 if the document is schemas valid, a positive error code
6221 * number otherwise and -1 in case of internal or API error.
6222 */
6223static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006224xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6225{
Daniel Veillard4255d502002-04-16 15:50:10 +00006226 xmlNodePtr root;
6227 xmlSchemaElementPtr elemDecl;
6228
6229 root = xmlDocGetRootElement(doc);
6230 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006231 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6232 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006233 }
6234 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006235 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6236 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006237 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006238 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6239 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006240 /*
6241 * special case whe elementFormDefault is unqualified for top-level elem.
6242 */
6243 if ((elemDecl == NULL) && (root->ns != NULL) &&
6244 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6245 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6246 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6247 root->name, NULL, NULL);
6248 }
6249
Daniel Veillard4255d502002-04-16 15:50:10 +00006250 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006251 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006252 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006253 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006254 }
6255 /*
6256 * Okay, start the recursive validation
6257 */
6258 xmlSchemaValidateElement(ctxt, root);
6259
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006260 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006261}
6262
6263/************************************************************************
6264 * *
6265 * SAX Validation code *
6266 * *
6267 ************************************************************************/
6268
6269/************************************************************************
6270 * *
6271 * Validation interfaces *
6272 * *
6273 ************************************************************************/
6274
6275/**
6276 * xmlSchemaNewValidCtxt:
6277 * @schema: a precompiled XML Schemas
6278 *
6279 * Create an XML Schemas validation context based on the given schema
6280 *
6281 * Returns the validation context or NULL in case of error
6282 */
6283xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006284xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6285{
Daniel Veillard4255d502002-04-16 15:50:10 +00006286 xmlSchemaValidCtxtPtr ret;
6287
6288 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6289 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006290 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006291 return (NULL);
6292 }
6293 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6294 ret->schema = schema;
6295 ret->attrNr = 0;
6296 ret->attrMax = 10;
6297 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006298 sizeof
6299 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006300 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006301 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6302 free(ret);
6303 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006304 }
6305 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6306 return (ret);
6307}
6308
6309/**
6310 * xmlSchemaFreeValidCtxt:
6311 * @ctxt: the schema validation context
6312 *
6313 * Free the resources associated to the schema validation context
6314 */
6315void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006316xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6317{
Daniel Veillard4255d502002-04-16 15:50:10 +00006318 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006319 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006320 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006321 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006322 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006323 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006324 xmlFree(ctxt);
6325}
6326
6327/**
6328 * xmlSchemaSetValidErrors:
6329 * @ctxt: a schema validation context
6330 * @err: the error function
6331 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006332 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006333 *
6334 * Set the error and warning callback informations
6335 */
6336void
6337xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006338 xmlSchemaValidityErrorFunc err,
6339 xmlSchemaValidityWarningFunc warn, void *ctx)
6340{
Daniel Veillard4255d502002-04-16 15:50:10 +00006341 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006342 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006343 ctxt->error = err;
6344 ctxt->warning = warn;
6345 ctxt->userData = ctx;
6346}
6347
6348/**
6349 * xmlSchemaValidateDoc:
6350 * @ctxt: a schema validation context
6351 * @doc: a parsed document tree
6352 *
6353 * Validate a document tree in memory.
6354 *
6355 * Returns 0 if the document is schemas valid, a positive error code
6356 * number otherwise and -1 in case of internal or API error.
6357 */
6358int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006359xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6360{
Daniel Veillard4255d502002-04-16 15:50:10 +00006361 int ret;
6362
6363 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006364 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006365
6366 ctxt->doc = doc;
6367 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006368 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006369}
6370
6371/**
6372 * xmlSchemaValidateStream:
6373 * @ctxt: a schema validation context
6374 * @input: the input to use for reading the data
6375 * @enc: an optional encoding information
6376 * @sax: a SAX handler for the resulting events
6377 * @user_data: the context to provide to the SAX handler.
6378 *
6379 * Validate a document tree in memory.
6380 *
6381 * Returns 0 if the document is schemas valid, a positive error code
6382 * number otherwise and -1 in case of internal or API error.
6383 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006384int
Daniel Veillard4255d502002-04-16 15:50:10 +00006385xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006386 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6387 xmlSAXHandlerPtr sax, void *user_data)
6388{
Daniel Veillard4255d502002-04-16 15:50:10 +00006389 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006390 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006391 ctxt->input = input;
6392 ctxt->enc = enc;
6393 ctxt->sax = sax;
6394 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006395 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006396}
6397
6398#endif /* LIBXML_SCHEMAS_ENABLED */