blob: f9e515335eec442da7804f58b2dc4be7ed33c5f8 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
15 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016#define IN_LIBXML
17#include "libxml.h"
18
19#ifdef LIBXML_SCHEMAS_ENABLED
20
21#include <string.h>
22#include <libxml/xmlmemory.h>
23#include <libxml/parser.h>
24#include <libxml/parserInternals.h>
25#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000026#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000027
28#include <libxml/xmlschemas.h>
29#include <libxml/schemasInternals.h>
30#include <libxml/xmlschemastypes.h>
31#include <libxml/xmlautomata.h>
32#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000033#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000034
Daniel Veillarda84c0b32003-06-02 16:58:46 +000035/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000036
Daniel Veillard82bbbd42003-05-11 20:16:09 +000037/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000038
Daniel Veillard82bbbd42003-05-11 20:16:09 +000039/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000040
Daniel Veillard118aed72002-09-24 14:13:13 +000041/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000042
Daniel Veillard4255d502002-04-16 15:50:10 +000043/* #define DEBUG_AUTOMATA 1 */
44
45#define UNBOUNDED (1 << 30)
46#define TODO \
47 xmlGenericError(xmlGenericErrorContext, \
48 "Unimplemented block at %s:%d\n", \
49 __FILE__, __LINE__);
50
Daniel Veillard5a872412002-05-22 06:40:27 +000051#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053/*
54 * The XML Schemas namespaces
55 */
56static const xmlChar *xmlSchemaNs = (const xmlChar *)
57 "http://www.w3.org/2001/XMLSchema";
58
59static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
60 "http://www.w3.org/2001/XMLSchema-instance";
61
62#define IS_SCHEMA(node, type) \
63 ((node != NULL) && (node->ns != NULL) && \
64 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
65 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
66
67#define XML_SCHEMAS_PARSE_ERROR 1
68
Daniel Veillardbd2904b2003-11-25 15:38:59 +000069#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
70
Daniel Veillard4255d502002-04-16 15:50:10 +000071struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000072 void *userData; /* user specific data block */
73 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
74 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +000075 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000076 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +000077 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +000078
Daniel Veillardbe9c6322003-11-22 20:37:51 +000079 xmlSchemaPtr topschema; /* The main schema */
80 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
81
Daniel Veillardd0c9c322003-10-10 00:49:42 +000082 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000083 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +000084 int counter;
85
Daniel Veillardbe9c6322003-11-22 20:37:51 +000086 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000087 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000088 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +000089
Daniel Veillardd0c9c322003-10-10 00:49:42 +000090 const char *buffer;
91 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000092
Daniel Veillard4255d502002-04-16 15:50:10 +000093 /*
94 * Used to build complex element content models
95 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000096 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000097 xmlAutomataStatePtr start;
98 xmlAutomataStatePtr end;
99 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000100
101 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000102 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard4255d502002-04-16 15:50:10 +0000103};
104
105
106#define XML_SCHEMAS_ATTR_UNKNOWN 1
107#define XML_SCHEMAS_ATTR_CHECKED 2
108
109typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
110typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
111struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000112 xmlAttrPtr attr;
113 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +0000114};
115
116/**
117 * xmlSchemaValidCtxt:
118 *
119 * A Schemas validation context
120 */
121
122struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 void *userData; /* user specific data block */
124 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
125 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000126 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000127
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000128 xmlSchemaPtr schema; /* The schema in use */
129 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000130 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000131 xmlCharEncoding enc;
132 xmlSAXHandlerPtr sax;
133 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000134
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000135 xmlDocPtr myDoc;
136 int err;
137 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000138
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000139 xmlNodePtr node;
140 xmlNodePtr cur;
141 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000142
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000143 xmlRegExecCtxtPtr regexp;
144 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000145
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000146 int attrNr;
147 int attrBase;
148 int attrMax;
149 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000150};
151
Daniel Veillard1d913862003-11-21 00:28:39 +0000152/*
153 * These are the entries in the schemas importSchemas hash table
154 */
155typedef struct _xmlSchemaImport xmlSchemaImport;
156typedef xmlSchemaImport *xmlSchemaImportPtr;
157struct _xmlSchemaImport {
158 const xmlChar *schemaLocation;
159 xmlSchemaPtr schema;
160};
Daniel Veillard4255d502002-04-16 15:50:10 +0000161
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000162/*
163 * These are the entries associated to includes in a schemas
164 */
165typedef struct _xmlSchemaInclude xmlSchemaInclude;
166typedef xmlSchemaInclude *xmlSchemaIncludePtr;
167struct _xmlSchemaInclude {
168 xmlSchemaIncludePtr next;
169
170 const xmlChar *schemaLocation;
171 xmlDocPtr doc;
172};
173
Daniel Veillard4255d502002-04-16 15:50:10 +0000174/************************************************************************
175 * *
176 * Some predeclarations *
177 * *
178 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
180 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000181 const xmlChar * value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000182
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000183static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
184 xmlSchemaPtr schema,
185 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000186/************************************************************************
187 * *
188 * Datatype error handlers *
189 * *
190 ************************************************************************/
191
192/**
193 * xmlSchemaPErrMemory:
194 * @node: a context node
195 * @extra: extra informations
196 *
197 * Handle an out of memory condition
198 */
199static void
200xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
201 const char *extra, xmlNodePtr node)
202{
203 if (ctxt != NULL)
204 ctxt->nberrors++;
205 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
206 extra);
207}
208
209/**
210 * xmlSchemaPErr:
211 * @ctxt: the parsing context
212 * @node: the context node
213 * @error: the error code
214 * @msg: the error message
215 * @str1: extra data
216 * @str2: extra data
217 *
218 * Handle a parser error
219 */
220static void
221xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
222 const char *msg, const xmlChar * str1, const xmlChar * str2)
223{
224 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *data = NULL;
227
228 if (ctxt != NULL) {
229 ctxt->nberrors++;
230 channel = ctxt->error;
231 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000232 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000233 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000234 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 error, XML_ERR_ERROR, NULL, 0,
236 (const char *) str1, (const char *) str2, NULL, 0, 0,
237 msg, str1, str2);
238}
239
240/**
241 * xmlSchemaPErr2:
242 * @ctxt: the parsing context
243 * @node: the context node
244 * @node: the current child
245 * @error: the error code
246 * @msg: the error message
247 * @str1: extra data
248 * @str2: extra data
249 *
250 * Handle a parser error
251 */
252static void
253xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
254 xmlNodePtr child, int error,
255 const char *msg, const xmlChar * str1, const xmlChar * str2)
256{
257 if (child != NULL)
258 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
259 else
260 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
261}
262
263/**
264 * xmlSchemaVTypeErrMemory:
265 * @node: a context node
266 * @extra: extra informations
267 *
268 * Handle an out of memory condition
269 */
270static void
271xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
272 const char *extra, xmlNodePtr node)
273{
274 if (ctxt != NULL) {
275 ctxt->nberrors++;
276 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
277 }
278 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
279 extra);
280}
281
282/**
283 * xmlSchemaVErr3:
284 * @ctxt: the validation context
285 * @node: the context node
286 * @error: the error code
287 * @msg: the error message
288 * @str1: extra data
289 * @str2: extra data
290 * @str3: extra data
291 *
292 * Handle a validation error
293 */
294static void
295xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
296 const char *msg, const xmlChar *str1, const xmlChar *str2,
297 const xmlChar *str3)
298{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000299 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000300 xmlGenericErrorFunc channel = NULL;
301 void *data = NULL;
302
303 if (ctxt != NULL) {
304 ctxt->nberrors++;
305 ctxt->err = error;
306 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000307 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000308 data = ctxt->userData;
309 }
310 /* reajust to global error numbers */
311 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000312 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000313 error, XML_ERR_ERROR, NULL, 0,
314 (const char *) str1, (const char *) str2,
315 (const char *) str3, 0, 0,
316 msg, str1, str2, str3);
317}
318/**
319 * xmlSchemaVErr:
320 * @ctxt: the validation context
321 * @node: the context node
322 * @error: the error code
323 * @msg: the error message
324 * @str1: extra data
325 * @str2: extra data
326 *
327 * Handle a validation error
328 */
329static void
330xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
331 const char *msg, const xmlChar * str1, const xmlChar * str2)
332{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000333 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000334 xmlGenericErrorFunc channel = NULL;
335 void *data = NULL;
336
337 if (ctxt != NULL) {
338 ctxt->nberrors++;
339 ctxt->err = error;
340 channel = ctxt->error;
341 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000342 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000343 }
344 /* reajust to global error numbers */
345 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000346 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000347 error, XML_ERR_ERROR, NULL, 0,
348 (const char *) str1, (const char *) str2, NULL, 0, 0,
349 msg, str1, str2);
350}
Daniel Veillard4255d502002-04-16 15:50:10 +0000351
352/************************************************************************
353 * *
354 * Allocation functions *
355 * *
356 ************************************************************************/
357
358/**
359 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000360 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000361 *
362 * Allocate a new Schema structure.
363 *
364 * Returns the newly allocated structure or NULL in case or error
365 */
366static xmlSchemaPtr
367xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
368{
369 xmlSchemaPtr ret;
370
371 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
372 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000373 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000374 return (NULL);
375 }
376 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000377 xmlDictReference(ctxt->dict);
378 ret->dict = ctxt->dict;
Daniel Veillard4255d502002-04-16 15:50:10 +0000379
380 return (ret);
381}
382
383/**
384 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000385 *
386 * Allocate a new Facet structure.
387 *
388 * Returns the newly allocated structure or NULL in case or error
389 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000390xmlSchemaFacetPtr
391xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000392{
393 xmlSchemaFacetPtr ret;
394
395 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
396 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000397 return (NULL);
398 }
399 memset(ret, 0, sizeof(xmlSchemaFacet));
400
401 return (ret);
402}
403
404/**
405 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000406 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000407 * @node: a node
408 *
409 * Allocate a new annotation structure.
410 *
411 * Returns the newly allocated structure or NULL in case or error
412 */
413static xmlSchemaAnnotPtr
414xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
415{
416 xmlSchemaAnnotPtr ret;
417
418 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
419 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000420 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000421 return (NULL);
422 }
423 memset(ret, 0, sizeof(xmlSchemaAnnot));
424 ret->content = node;
425 return (ret);
426}
427
428/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000429 * xmlSchemaFreeAnnot:
430 * @annot: a schema type structure
431 *
432 * Deallocate a annotation structure
433 */
434static void
435xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
436{
437 if (annot == NULL)
438 return;
439 xmlFree(annot);
440}
441
442/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000443 * xmlSchemaFreeImport:
444 * @import: a schema import structure
445 *
446 * Deallocate an import structure
447 */
448static void
449xmlSchemaFreeImport(xmlSchemaImportPtr import)
450{
451 if (import == NULL)
452 return;
453
454 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000455 xmlFree(import);
456}
457
458/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000459 * xmlSchemaFreeInclude:
460 * @include: a schema include structure
461 *
462 * Deallocate an include structure
463 */
464static void
465xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
466{
467 if (include == NULL)
468 return;
469
470 xmlFreeDoc(include->doc);
471 xmlFree(include);
472}
473
474/**
475 * xmlSchemaFreeIncludeList:
476 * @includes: a schema include list
477 *
478 * Deallocate an include structure
479 */
480static void
481xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
482{
483 xmlSchemaIncludePtr next;
484
485 while (includes != NULL) {
486 next = includes->next;
487 xmlSchemaFreeInclude(includes);
488 includes = next;
489 }
490}
491
492/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000493 * xmlSchemaFreeNotation:
494 * @schema: a schema notation structure
495 *
496 * Deallocate a Schema Notation structure.
497 */
498static void
499xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
500{
501 if (nota == NULL)
502 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000503 xmlFree(nota);
504}
505
506/**
507 * xmlSchemaFreeAttribute:
508 * @schema: a schema attribute structure
509 *
510 * Deallocate a Schema Attribute structure.
511 */
512static void
513xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
514{
515 if (attr == NULL)
516 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000517 xmlFree(attr);
518}
519
520/**
521 * xmlSchemaFreeAttributeGroup:
522 * @schema: a schema attribute group structure
523 *
524 * Deallocate a Schema Attribute Group structure.
525 */
526static void
527xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
528{
529 if (attr == NULL)
530 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000531 xmlFree(attr);
532}
533
534/**
535 * xmlSchemaFreeElement:
536 * @schema: a schema element structure
537 *
538 * Deallocate a Schema Element structure.
539 */
540static void
541xmlSchemaFreeElement(xmlSchemaElementPtr elem)
542{
543 if (elem == NULL)
544 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000545 if (elem->annot != NULL)
546 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000547 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000548 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000549 xmlFree(elem);
550}
551
552/**
553 * xmlSchemaFreeFacet:
554 * @facet: a schema facet structure
555 *
556 * Deallocate a Schema Facet structure.
557 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000558void
Daniel Veillard4255d502002-04-16 15:50:10 +0000559xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
560{
561 if (facet == NULL)
562 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000563 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000564 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000565 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000566 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000567 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000568 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000569 xmlFree(facet);
570}
571
572/**
573 * xmlSchemaFreeType:
574 * @type: a schema type structure
575 *
576 * Deallocate a Schema Type structure.
577 */
578void
579xmlSchemaFreeType(xmlSchemaTypePtr type)
580{
581 if (type == NULL)
582 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000583 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000584 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000585 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000586 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000587
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000588 facet = type->facets;
589 while (facet != NULL) {
590 next = facet->next;
591 xmlSchemaFreeFacet(facet);
592 facet = next;
593 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000594 }
595 xmlFree(type);
596}
597
598/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000599 * xmlSchemaFreeTypeList:
600 * @type: a schema type structure
601 *
602 * Deallocate a Schema Type structure.
603 */
604static void
605xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
606{
607 xmlSchemaTypePtr next;
608
609 while (type != NULL) {
610 next = type->redef;
611 xmlSchemaFreeType(type);
612 type = next;
613 }
614}
615
616/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000617 * xmlSchemaFree:
618 * @schema: a schema structure
619 *
620 * Deallocate a Schema structure.
621 */
622void
623xmlSchemaFree(xmlSchemaPtr schema)
624{
625 if (schema == NULL)
626 return;
627
Daniel Veillard4255d502002-04-16 15:50:10 +0000628 if (schema->notaDecl != NULL)
629 xmlHashFree(schema->notaDecl,
630 (xmlHashDeallocator) xmlSchemaFreeNotation);
631 if (schema->attrDecl != NULL)
632 xmlHashFree(schema->attrDecl,
633 (xmlHashDeallocator) xmlSchemaFreeAttribute);
634 if (schema->attrgrpDecl != NULL)
635 xmlHashFree(schema->attrgrpDecl,
636 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
637 if (schema->elemDecl != NULL)
638 xmlHashFree(schema->elemDecl,
639 (xmlHashDeallocator) xmlSchemaFreeElement);
640 if (schema->typeDecl != NULL)
641 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000642 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000643 if (schema->groupDecl != NULL)
644 xmlHashFree(schema->groupDecl,
645 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000646 if (schema->schemasImports != NULL)
647 xmlHashFree(schema->schemasImports,
648 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000649 if (schema->includes != NULL) {
650 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
651 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000652 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000653 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +0000654 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000655 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000656 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000657
658 xmlFree(schema);
659}
660
661/************************************************************************
662 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000663 * Debug functions *
664 * *
665 ************************************************************************/
666
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000667#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000668
Daniel Veillard4255d502002-04-16 15:50:10 +0000669/**
670 * xmlSchemaElementDump:
671 * @elem: an element
672 * @output: the file output
673 *
674 * Dump the element
675 */
676static void
677xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000678 const xmlChar * name ATTRIBUTE_UNUSED,
679 const xmlChar * context ATTRIBUTE_UNUSED,
680 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000681{
682 if (elem == NULL)
683 return;
684
685 fprintf(output, "Element ");
686 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000687 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000688 fprintf(output, ": %s ", elem->name);
689 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000690 fprintf(output, "namespace '%s' ", namespace);
691
Daniel Veillard4255d502002-04-16 15:50:10 +0000692 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000693 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000694 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000695 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000696 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000697 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000698 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000699 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000700 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000701 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000702 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000703 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000704 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000706 fprintf(output, "\n");
707 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000708 fprintf(output, " ");
709 if (elem->minOccurs != 1)
710 fprintf(output, "min: %d ", elem->minOccurs);
711 if (elem->maxOccurs >= UNBOUNDED)
712 fprintf(output, "max: unbounded\n");
713 else if (elem->maxOccurs != 1)
714 fprintf(output, "max: %d\n", elem->maxOccurs);
715 else
716 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000717 }
718 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000719 fprintf(output, " type: %s", elem->namedType);
720 if (elem->namedTypeNs != NULL)
721 fprintf(output, " ns %s\n", elem->namedTypeNs);
722 else
723 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000724 }
725 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000726 fprintf(output, " substitutionGroup: %s", elem->substGroup);
727 if (elem->substGroupNs != NULL)
728 fprintf(output, " ns %s\n", elem->substGroupNs);
729 else
730 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000731 }
732 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000733 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000734}
735
736/**
737 * xmlSchemaAnnotDump:
738 * @output: the file output
739 * @annot: a annotation
740 *
741 * Dump the annotation
742 */
743static void
744xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
745{
746 xmlChar *content;
747
748 if (annot == NULL)
749 return;
750
751 content = xmlNodeGetContent(annot->content);
752 if (content != NULL) {
753 fprintf(output, " Annot: %s\n", content);
754 xmlFree(content);
755 } else
756 fprintf(output, " Annot: empty\n");
757}
758
759/**
760 * xmlSchemaTypeDump:
761 * @output: the file output
762 * @type: a type structure
763 *
764 * Dump a SchemaType structure
765 */
766static void
767xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
768{
769 if (type == NULL) {
770 fprintf(output, "Type: NULL\n");
771 return;
772 }
773 fprintf(output, "Type: ");
774 if (type->name != NULL)
775 fprintf(output, "%s, ", type->name);
776 else
777 fprintf(output, "no name");
778 switch (type->type) {
779 case XML_SCHEMA_TYPE_BASIC:
780 fprintf(output, "basic ");
781 break;
782 case XML_SCHEMA_TYPE_SIMPLE:
783 fprintf(output, "simple ");
784 break;
785 case XML_SCHEMA_TYPE_COMPLEX:
786 fprintf(output, "complex ");
787 break;
788 case XML_SCHEMA_TYPE_SEQUENCE:
789 fprintf(output, "sequence ");
790 break;
791 case XML_SCHEMA_TYPE_CHOICE:
792 fprintf(output, "choice ");
793 break;
794 case XML_SCHEMA_TYPE_ALL:
795 fprintf(output, "all ");
796 break;
797 case XML_SCHEMA_TYPE_UR:
798 fprintf(output, "ur ");
799 break;
800 case XML_SCHEMA_TYPE_RESTRICTION:
801 fprintf(output, "restriction ");
802 break;
803 case XML_SCHEMA_TYPE_EXTENSION:
804 fprintf(output, "extension ");
805 break;
806 default:
807 fprintf(output, "unknowntype%d ", type->type);
808 break;
809 }
810 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000811 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000812 }
813 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000814 case XML_SCHEMA_CONTENT_UNKNOWN:
815 fprintf(output, "unknown ");
816 break;
817 case XML_SCHEMA_CONTENT_EMPTY:
818 fprintf(output, "empty ");
819 break;
820 case XML_SCHEMA_CONTENT_ELEMENTS:
821 fprintf(output, "element ");
822 break;
823 case XML_SCHEMA_CONTENT_MIXED:
824 fprintf(output, "mixed ");
825 break;
826 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
827 fprintf(output, "mixed_or_elems ");
828 break;
829 case XML_SCHEMA_CONTENT_BASIC:
830 fprintf(output, "basic ");
831 break;
832 case XML_SCHEMA_CONTENT_SIMPLE:
833 fprintf(output, "simple ");
834 break;
835 case XML_SCHEMA_CONTENT_ANY:
836 fprintf(output, "any ");
837 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000838 }
839 fprintf(output, "\n");
840 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000841 fprintf(output, " ");
842 if (type->minOccurs != 1)
843 fprintf(output, "min: %d ", type->minOccurs);
844 if (type->maxOccurs >= UNBOUNDED)
845 fprintf(output, "max: unbounded\n");
846 else if (type->maxOccurs != 1)
847 fprintf(output, "max: %d\n", type->maxOccurs);
848 else
849 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000850 }
851 if (type->annot != NULL)
852 xmlSchemaAnnotDump(output, type->annot);
853 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000854 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000855
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000856 fprintf(output, " subtypes: ");
857 while (sub != NULL) {
858 fprintf(output, "%s ", sub->name);
859 sub = sub->next;
860 }
861 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000862 }
863
864}
865
866/**
867 * xmlSchemaDump:
868 * @output: the file output
869 * @schema: a schema structure
870 *
871 * Dump a Schema structure.
872 */
873void
874xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
875{
876 if (schema == NULL) {
877 fprintf(output, "Schemas: NULL\n");
878 return;
879 }
880 fprintf(output, "Schemas: ");
881 if (schema->name != NULL)
882 fprintf(output, "%s, ", schema->name);
883 else
884 fprintf(output, "no name, ");
885 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000886 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000887 else
888 fprintf(output, "no target namespace");
889 fprintf(output, "\n");
890 if (schema->annot != NULL)
891 xmlSchemaAnnotDump(output, schema->annot);
892
893 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
894 output);
895 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000896 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000897}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000898#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000899
900/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000901 * *
902 * Utilities *
903 * *
904 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000905
906/**
907 * xmlSchemaGetProp:
908 * @ctxt: the parser context
909 * @node: the node
910 * @name: the property name
911 *
912 * Read a attribute value and internalize the string
913 *
914 * Returns the string or NULL if not present.
915 */
916static const xmlChar *
917xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
918 const char *name)
919{
920 xmlChar *val;
921 const xmlChar *ret;
922
923 val = xmlGetProp(node, BAD_CAST name);
924 if (val == NULL)
925 return(NULL);
926 ret = xmlDictLookup(ctxt->dict, val, -1);
927 xmlFree(val);
928 return(ret);
929}
930
931/**
932 * xmlSchemaGetNamespace:
933 * @ctxt: the parser context
934 * @schema: the schemas containing the declaration
935 * @node: the node
936 * @qname: the QName to analyze
937 *
938 * Find the namespace name for the given declaration.
939 *
940 * Returns the local name for that declaration, as well as the namespace name
941 */
942static const xmlChar *
943xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
944 xmlNodePtr node, const xmlChar *qname,
945 const xmlChar **namespace) {
946 int len;
947 const xmlChar *name, *prefix, *def = NULL;
948 xmlNsPtr ns;
949
950 *namespace = NULL;
951
952 if (xmlStrEqual(node->name, BAD_CAST "element") ||
953 xmlStrEqual(node->name, BAD_CAST "attribute") ||
954 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
955 xmlStrEqual(node->name, BAD_CAST "complexType")) {
956 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
957 }
958
959 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
960 name = xmlSplitQName3(qname, &len);
961 if (name == NULL) {
962 if (def == NULL) {
963 if (xmlStrEqual(node->name, BAD_CAST "element")) {
964 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
965 *namespace = schema->targetNamespace;
966 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
967 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
968 *namespace = schema->targetNamespace;
969 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
970 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
971 *namespace = schema->targetNamespace;
972 }
973 } else {
974 *namespace = def;
975 }
976 return(qname);
977 }
978 name = xmlDictLookup(ctxt->dict, name, -1);
979 prefix = xmlDictLookup(ctxt->dict, qname, len);
980 if (def != NULL) {
981 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
982 "%s: presence of both prefix %s and targetNamespace\n",
983 node->name, prefix);
984 }
985 ns = xmlSearchNs(node->doc, node, prefix);
986 if (ns == NULL) {
987 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
988 "%s: the QName prefix %s is undefined\n",
989 node->name, prefix);
990 return(name);
991 }
992 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
993 return(name);
994}
995
996/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +0000997 * *
998 * Parsing functions *
999 * *
1000 ************************************************************************/
1001
1002/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001003 * xmlSchemaGetElem:
1004 * @schema: the schemas context
1005 * @name: the element name
1006 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001007 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001008 *
1009 * Lookup a an element in the schemas or the accessible schemas
1010 *
1011 * Returns the element definition or NULL if not found.
1012 */
1013static xmlSchemaElementPtr
1014xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001015 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001016{
1017 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001018 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001019
1020 if ((name == NULL) || (schema == NULL))
1021 return (NULL);
1022
1023 if (namespace == NULL) {
1024 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001025 if ((ret != NULL) &&
1026 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001027 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001028 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001029 } else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
1030 if (xmlStrEqual(namespace, schema->targetNamespace))
1031 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1032 else
1033 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001034 if ((ret != NULL) &&
1035 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001036 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001037 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001038 } else {
1039 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001040 if ((ret != NULL) &&
1041 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001042 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001043 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001044 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001045 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001046 import = xmlHashLookup(schema->schemasImports, namespace);
1047 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001048 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001049#ifdef DEBUG
1050 if (ret == NULL) {
1051 if (namespace == NULL)
1052 fprintf(stderr, "Unable to lookup type %s", name);
1053 else
1054 fprintf(stderr, "Unable to lookup type %s:%s", name,
1055 namespace);
1056 }
1057#endif
1058 return (ret);
1059}
1060
1061/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001062 * xmlSchemaGetType:
1063 * @schema: the schemas context
1064 * @name: the type name
1065 * @ns: the type namespace
1066 *
1067 * Lookup a type in the schemas or the predefined types
1068 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001069 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001070 */
1071static xmlSchemaTypePtr
1072xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001073 const xmlChar * namespace)
1074{
Daniel Veillard4255d502002-04-16 15:50:10 +00001075 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001076 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001077
1078 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001079 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001080 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001081 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1082 if (ret != NULL)
1083 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001084 }
1085 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001086 if (ret != NULL)
1087 return (ret);
1088 import = xmlHashLookup(schema->schemasImports, namespace);
1089 if (import != NULL)
1090 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001091#ifdef DEBUG
1092 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001093 if (namespace == NULL)
1094 fprintf(stderr, "Unable to lookup type %s", name);
1095 else
1096 fprintf(stderr, "Unable to lookup type %s:%s", name,
1097 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001098 }
1099#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001100 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001101}
1102
1103/************************************************************************
1104 * *
1105 * Parsing functions *
1106 * *
1107 ************************************************************************/
1108
1109#define IS_BLANK_NODE(n) \
1110 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1111
1112/**
1113 * xmlSchemaIsBlank:
1114 * @str: a string
1115 *
1116 * Check if a string is ignorable
1117 *
1118 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1119 */
1120static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001121xmlSchemaIsBlank(xmlChar * str)
1122{
Daniel Veillard4255d502002-04-16 15:50:10 +00001123 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001124 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001125 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001126 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001127 return (0);
1128 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001129 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001130 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001131}
1132
1133/**
1134 * xmlSchemaAddNotation:
1135 * @ctxt: a schema validation context
1136 * @schema: the schema being built
1137 * @name: the item name
1138 *
1139 * Add an XML schema Attrribute declaration
1140 * *WARNING* this interface is highly subject to change
1141 *
1142 * Returns the new struture or NULL in case of error
1143 */
1144static xmlSchemaNotationPtr
1145xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001146 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001147{
1148 xmlSchemaNotationPtr ret = NULL;
1149 int val;
1150
1151 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1152 return (NULL);
1153
1154 if (schema->notaDecl == NULL)
1155 schema->notaDecl = xmlHashCreate(10);
1156 if (schema->notaDecl == NULL)
1157 return (NULL);
1158
1159 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1160 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001161 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001162 return (NULL);
1163 }
1164 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001165 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001166 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1167 ret);
1168 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001169 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1170 XML_SCHEMAP_REDEFINED_NOTATION,
1171 "Notation %s already defined\n",
1172 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001173 xmlFree(ret);
1174 return (NULL);
1175 }
1176 return (ret);
1177}
1178
1179
1180/**
1181 * xmlSchemaAddAttribute:
1182 * @ctxt: a schema validation context
1183 * @schema: the schema being built
1184 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001185 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001186 *
1187 * Add an XML schema Attrribute declaration
1188 * *WARNING* this interface is highly subject to change
1189 *
1190 * Returns the new struture or NULL in case of error
1191 */
1192static xmlSchemaAttributePtr
1193xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001194 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001195{
1196 xmlSchemaAttributePtr ret = NULL;
1197 int val;
1198
1199 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1200 return (NULL);
1201
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001202#ifdef DEBUG
1203 fprintf(stderr, "Adding attribute %s\n", name);
1204 if (namespace != NULL)
1205 fprintf(stderr, " target namespace %s\n", namespace);
1206#endif
1207
Daniel Veillard4255d502002-04-16 15:50:10 +00001208 if (schema->attrDecl == NULL)
1209 schema->attrDecl = xmlHashCreate(10);
1210 if (schema->attrDecl == NULL)
1211 return (NULL);
1212
1213 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1214 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001215 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001216 return (NULL);
1217 }
1218 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001219 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1220 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001221 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001222 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001223 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001224 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1225 XML_SCHEMAP_REDEFINED_ATTR,
1226 "Attribute %s already defined\n",
1227 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001228 xmlFree(ret);
1229 return (NULL);
1230 }
1231 return (ret);
1232}
1233
1234/**
1235 * xmlSchemaAddAttributeGroup:
1236 * @ctxt: a schema validation context
1237 * @schema: the schema being built
1238 * @name: the item name
1239 *
1240 * Add an XML schema Attrribute Group declaration
1241 *
1242 * Returns the new struture or NULL in case of error
1243 */
1244static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001245xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1246 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001247{
1248 xmlSchemaAttributeGroupPtr ret = NULL;
1249 int val;
1250
1251 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1252 return (NULL);
1253
1254 if (schema->attrgrpDecl == NULL)
1255 schema->attrgrpDecl = xmlHashCreate(10);
1256 if (schema->attrgrpDecl == NULL)
1257 return (NULL);
1258
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001259 ret =
1260 (xmlSchemaAttributeGroupPtr)
1261 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001262 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001263 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001264 return (NULL);
1265 }
1266 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001267 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001268 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001269 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001270 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001271 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1272 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1273 "Attribute group %s already defined\n",
1274 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001275 xmlFree(ret);
1276 return (NULL);
1277 }
1278 return (ret);
1279}
1280
1281/**
1282 * xmlSchemaAddElement:
1283 * @ctxt: a schema validation context
1284 * @schema: the schema being built
1285 * @name: the type name
1286 * @namespace: the type namespace
1287 *
1288 * Add an XML schema Element declaration
1289 * *WARNING* this interface is highly subject to change
1290 *
1291 * Returns the new struture or NULL in case of error
1292 */
1293static xmlSchemaElementPtr
1294xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1295 const xmlChar * name, const xmlChar * namespace)
1296{
1297 xmlSchemaElementPtr ret = NULL;
1298 int val;
1299
1300 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1301 return (NULL);
1302
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001303#ifdef DEBUG
1304 fprintf(stderr, "Adding element %s\n", name);
1305 if (namespace != NULL)
1306 fprintf(stderr, " target namespace %s\n", namespace);
1307#endif
1308
Daniel Veillard4255d502002-04-16 15:50:10 +00001309 if (schema->elemDecl == NULL)
1310 schema->elemDecl = xmlHashCreate(10);
1311 if (schema->elemDecl == NULL)
1312 return (NULL);
1313
1314 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1315 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001316 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001317 return (NULL);
1318 }
1319 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001320 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1321 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001322 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001323 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001324 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001325 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001326
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001327 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001328 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1329 namespace, ret);
1330 if (val != 0) {
1331 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1332 XML_SCHEMAP_REDEFINED_ELEMENT,
1333 "Element %s already defined\n",
1334 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001335 xmlFree(ret);
1336 return (NULL);
1337 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001338 }
1339 return (ret);
1340}
1341
1342/**
1343 * xmlSchemaAddType:
1344 * @ctxt: a schema validation context
1345 * @schema: the schema being built
1346 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001347 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001348 *
1349 * Add an XML schema Simple Type definition
1350 * *WARNING* this interface is highly subject to change
1351 *
1352 * Returns the new struture or NULL in case of error
1353 */
1354static xmlSchemaTypePtr
1355xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001356 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001357{
1358 xmlSchemaTypePtr ret = NULL;
1359 int val;
1360
1361 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1362 return (NULL);
1363
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001364#ifdef DEBUG
1365 fprintf(stderr, "Adding type %s\n", name);
1366 if (namespace != NULL)
1367 fprintf(stderr, " target namespace %s\n", namespace);
1368#endif
1369
Daniel Veillard4255d502002-04-16 15:50:10 +00001370 if (schema->typeDecl == NULL)
1371 schema->typeDecl = xmlHashCreate(10);
1372 if (schema->typeDecl == NULL)
1373 return (NULL);
1374
1375 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1376 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001377 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001378 return (NULL);
1379 }
1380 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001381 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001382 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001383 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001384 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001385 if (ctxt->includes == 0) {
1386 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1387 XML_SCHEMAP_REDEFINED_TYPE,
1388 "Type %s already defined\n",
1389 name, NULL);
1390 xmlFree(ret);
1391 return (NULL);
1392 } else {
1393 xmlSchemaTypePtr prev;
1394
1395 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1396 if (prev == NULL) {
1397 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1398 XML_ERR_INTERNAL_ERROR,
1399 "Internal error on type %s definition\n",
1400 name, NULL);
1401 xmlFree(ret);
1402 return (NULL);
1403 }
1404 ret->redef = prev->redef;
1405 prev->redef = ret;
1406 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001407 }
1408 ret->minOccurs = 1;
1409 ret->maxOccurs = 1;
1410
1411 return (ret);
1412}
1413
1414/**
1415 * xmlSchemaAddGroup:
1416 * @ctxt: a schema validation context
1417 * @schema: the schema being built
1418 * @name: the group name
1419 *
1420 * Add an XML schema Group definition
1421 *
1422 * Returns the new struture or NULL in case of error
1423 */
1424static xmlSchemaTypePtr
1425xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001426 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001427{
1428 xmlSchemaTypePtr ret = NULL;
1429 int val;
1430
1431 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1432 return (NULL);
1433
1434 if (schema->groupDecl == NULL)
1435 schema->groupDecl = xmlHashCreate(10);
1436 if (schema->groupDecl == NULL)
1437 return (NULL);
1438
1439 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1440 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001441 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001442 return (NULL);
1443 }
1444 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001445 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001446 val =
1447 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1448 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001449 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001450 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1451 XML_SCHEMAP_REDEFINED_GROUP,
1452 "Group %s already defined\n",
1453 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001454 xmlFree(ret);
1455 return (NULL);
1456 }
1457 ret->minOccurs = 1;
1458 ret->maxOccurs = 1;
1459
1460 return (ret);
1461}
1462
1463/************************************************************************
1464 * *
1465 * Utilities for parsing *
1466 * *
1467 ************************************************************************/
1468
1469/**
1470 * xmlGetQNameProp:
1471 * @ctxt: a schema validation context
1472 * @node: a subtree containing XML Schema informations
1473 * @name: the attribute name
1474 * @namespace: the result namespace if any
1475 *
1476 * Extract a QName Attribute value
1477 *
1478 * Returns the NCName or NULL if not found, and also update @namespace
1479 * with the namespace URI
1480 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001481static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001482xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001483 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001484{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001485 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001486 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001487 const xmlChar *ret, *prefix;
1488 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001489
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001490 *namespace = NULL;
1491 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001492 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001493 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001494
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001495 ret = xmlSplitQName3(val, &len);
1496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001497 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001498 }
1499 ret = xmlDictLookup(ctxt->dict, ret, -1);
1500 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001501
1502 ns = xmlSearchNs(node->doc, node, prefix);
1503 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001504 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1505 "Attribute %s: the QName prefix %s is undefined\n",
1506 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001507 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001508 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001509 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001510 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001511}
1512
1513/**
1514 * xmlGetMaxOccurs:
1515 * @ctxt: a schema validation context
1516 * @node: a subtree containing XML Schema informations
1517 *
1518 * Get the maxOccurs property
1519 *
1520 * Returns the default if not found, or the value
1521 */
1522static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001523xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1524{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001525 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001526 int ret = 0;
1527
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001528 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001529 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001530 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001531
1532 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001533 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001534 }
1535
1536 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001537 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001538 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001539 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001540 ret = ret * 10 + (*cur - '0');
1541 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001542 }
William M. Brack76e95df2003-10-18 16:20:14 +00001543 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001544 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001545 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001546 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1547 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001548 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001549 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001550 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001551}
1552
1553/**
1554 * xmlGetMinOccurs:
1555 * @ctxt: a schema validation context
1556 * @node: a subtree containing XML Schema informations
1557 *
1558 * Get the minOccurs property
1559 *
1560 * Returns the default if not found, or the value
1561 */
1562static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001563xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1564{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001565 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001566 int ret = 0;
1567
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001568 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001569 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001570 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001571
1572 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001573 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001574 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001575 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576 ret = ret * 10 + (*cur - '0');
1577 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001578 }
William M. Brack76e95df2003-10-18 16:20:14 +00001579 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001580 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001581 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001582 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1583 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001584 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001585 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001586 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001587}
1588
1589/**
1590 * xmlGetBooleanProp:
1591 * @ctxt: a schema validation context
1592 * @node: a subtree containing XML Schema informations
1593 * @name: the attribute name
1594 * @def: the default value
1595 *
1596 * Get is a bolean property is set
1597 *
1598 * Returns the default if not found, 0 if found to be false,
1599 * 1 if found to be true
1600 */
1601static int
1602xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001603 const char *name, int def)
1604{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001605 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001606
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001607 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001608 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001609 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001610
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001611 if (xmlStrEqual(val, BAD_CAST "true"))
1612 def = 1;
1613 else if (xmlStrEqual(val, BAD_CAST "false"))
1614 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001615 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001616 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1617 "Attribute %s: the value %s is not boolean\n",
1618 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001619 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001620 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001621}
1622
1623/************************************************************************
1624 * *
1625 * Shema extraction from an Infoset *
1626 * *
1627 ************************************************************************/
1628static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1629 ctxt, xmlSchemaPtr schema,
1630 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001631static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1632 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001633 xmlSchemaPtr schema,
1634 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001635static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1636 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001637 xmlSchemaPtr schema,
1638 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001639 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001640static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1641 xmlSchemaPtr schema,
1642 xmlNodePtr node);
1643static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1644 xmlSchemaPtr schema,
1645 xmlNodePtr node);
1646static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1647 ctxt,
1648 xmlSchemaPtr schema,
1649 xmlNodePtr node);
1650static xmlSchemaAttributeGroupPtr
1651xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1652 xmlSchemaPtr schema, xmlNodePtr node);
1653static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1654 xmlSchemaPtr schema,
1655 xmlNodePtr node);
1656static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1657 xmlSchemaPtr schema,
1658 xmlNodePtr node);
1659static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001660xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1661 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001662
1663/**
1664 * xmlSchemaParseAttrDecls:
1665 * @ctxt: a schema validation context
1666 * @schema: the schema being built
1667 * @node: a subtree containing XML Schema informations
1668 * @type: the hosting type
1669 *
1670 * parse a XML schema attrDecls declaration corresponding to
1671 * <!ENTITY % attrDecls
1672 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1673 */
1674static xmlNodePtr
1675xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1676 xmlNodePtr child, xmlSchemaTypePtr type)
1677{
1678 xmlSchemaAttributePtr lastattr, attr;
1679
1680 lastattr = NULL;
1681 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001682 (IS_SCHEMA(child, "attributeGroup"))) {
1683 attr = NULL;
1684 if (IS_SCHEMA(child, "attribute")) {
1685 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1686 } else if (IS_SCHEMA(child, "attributeGroup")) {
1687 attr = (xmlSchemaAttributePtr)
1688 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1689 }
1690 if (attr != NULL) {
1691 if (lastattr == NULL) {
1692 type->attributes = attr;
1693 lastattr = attr;
1694 } else {
1695 lastattr->next = attr;
1696 lastattr = attr;
1697 }
1698 }
1699 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001700 }
1701 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001702 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1703 if (attr != NULL) {
1704 if (lastattr == NULL) {
1705 type->attributes = attr;
1706 lastattr = attr;
1707 } else {
1708 lastattr->next = attr;
1709 lastattr = attr;
1710 }
1711 }
1712 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001713 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001714 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001715}
1716
1717/**
1718 * xmlSchemaParseAnnotation:
1719 * @ctxt: a schema validation context
1720 * @schema: the schema being built
1721 * @node: a subtree containing XML Schema informations
1722 *
1723 * parse a XML schema Attrribute declaration
1724 * *WARNING* this interface is highly subject to change
1725 *
1726 * Returns -1 in case of error, 0 if the declaration is inproper and
1727 * 1 in case of success.
1728 */
1729static xmlSchemaAnnotPtr
1730xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1731 xmlNodePtr node)
1732{
1733 xmlSchemaAnnotPtr ret;
1734
1735 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1736 return (NULL);
1737 ret = xmlSchemaNewAnnot(ctxt, node);
1738
1739 return (ret);
1740}
1741
1742/**
1743 * xmlSchemaParseFacet:
1744 * @ctxt: a schema validation context
1745 * @schema: the schema being built
1746 * @node: a subtree containing XML Schema informations
1747 *
1748 * parse a XML schema Facet declaration
1749 * *WARNING* this interface is highly subject to change
1750 *
1751 * Returns the new type structure or NULL in case of error
1752 */
1753static xmlSchemaFacetPtr
1754xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001755 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001756{
1757 xmlSchemaFacetPtr facet;
1758 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001759 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001760
1761 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1762 return (NULL);
1763
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001764 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001765 if (facet == NULL) {
1766 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1767 return (NULL);
1768 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001769 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001770 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001771 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001772 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1773 "Facet %s has no value\n", node->name, NULL);
1774 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001775 return (NULL);
1776 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001777 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001778 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001779 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001780 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001781 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001782 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001783 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001784 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001785 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001786 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001787 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001788 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001789 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001790 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001791 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001792 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001793 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001794 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001795 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001796 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001797 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001798 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1799 } else if (IS_SCHEMA(node, "minLength")) {
1800 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1801 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001802 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1803 "Unknown facet type %s\n", node->name, NULL);
1804 xmlSchemaFreeFacet(facet);
1805 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001807 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001808 facet->value = value;
1809 child = node->children;
1810
1811 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001812 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1813 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001814 }
1815 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001816 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1817 "Facet %s has unexpected child content\n",
1818 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 }
1820 return (facet);
1821}
1822
1823/**
1824 * xmlSchemaParseAny:
1825 * @ctxt: a schema validation context
1826 * @schema: the schema being built
1827 * @node: a subtree containing XML Schema informations
1828 *
1829 * parse a XML schema Any declaration
1830 * *WARNING* this interface is highly subject to change
1831 *
1832 * Returns the new type structure or NULL in case of error
1833 */
1834static xmlSchemaTypePtr
1835xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1836 xmlNodePtr node)
1837{
1838 xmlSchemaTypePtr type;
1839 xmlNodePtr child = NULL;
1840 xmlChar name[30];
1841
1842 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1843 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001844 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001845 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001846 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001847 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001848 type->node = node;
1849 type->type = XML_SCHEMA_TYPE_ANY;
1850 child = node->children;
1851 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1852 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1853
1854 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001855 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1856 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001857 }
1858 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001859 xmlSchemaPErr2(ctxt, node, child,
1860 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1861 "Sequence %s has unexpected content\n", type->name,
1862 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001863 }
1864
1865 return (type);
1866}
1867
1868/**
1869 * xmlSchemaParseNotation:
1870 * @ctxt: a schema validation context
1871 * @schema: the schema being built
1872 * @node: a subtree containing XML Schema informations
1873 *
1874 * parse a XML schema Notation declaration
1875 *
1876 * Returns the new structure or NULL in case of error
1877 */
1878static xmlSchemaNotationPtr
1879xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001880 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001881{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001882 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001883 xmlSchemaNotationPtr ret;
1884 xmlNodePtr child = NULL;
1885
1886 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1887 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001888 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001889 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001890 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1891 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001892 return (NULL);
1893 }
1894 ret = xmlSchemaAddNotation(ctxt, schema, name);
1895 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001896 return (NULL);
1897 }
1898 child = node->children;
1899 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001900 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1901 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001902 }
1903 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001904 xmlSchemaPErr2(ctxt, node, child,
1905 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1906 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001907 }
1908
1909 return (ret);
1910}
1911
1912/**
1913 * xmlSchemaParseAnyAttribute:
1914 * @ctxt: a schema validation context
1915 * @schema: the schema being built
1916 * @node: a subtree containing XML Schema informations
1917 *
1918 * parse a XML schema AnyAttrribute declaration
1919 * *WARNING* this interface is highly subject to change
1920 *
1921 * Returns an attribute def structure or NULL
1922 */
1923static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001924xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1925 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001926{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001927 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001928 xmlSchemaAttributePtr ret;
1929 xmlNodePtr child = NULL;
1930 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001931 const xmlChar *local, *ns;
1932
Daniel Veillard4255d502002-04-16 15:50:10 +00001933
1934 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1935 return (NULL);
1936
1937 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001938 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1939 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001940 if (ret == NULL) {
1941 return (NULL);
1942 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001943 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1944 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001945 if ((processContents == NULL)
1946 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1947 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1948 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1949 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1950 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1951 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001952 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001953 xmlSchemaPErr2(ctxt, node, child,
1954 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1955 "anyAttribute has unexpected content for processContents: %s\n",
1956 processContents, NULL);
1957 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001958 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001959
1960 child = node->children;
1961 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001962 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1963 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001964 }
1965 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001966 xmlSchemaPErr2(ctxt, node, child,
1967 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1968 "anyAttribute %s has unexpected content\n",
1969 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001970 }
1971
1972 return (ret);
1973}
1974
1975
1976/**
1977 * xmlSchemaParseAttribute:
1978 * @ctxt: a schema validation context
1979 * @schema: the schema being built
1980 * @node: a subtree containing XML Schema informations
1981 *
1982 * parse a XML schema Attrribute declaration
1983 * *WARNING* this interface is highly subject to change
1984 *
1985 * Returns -1 in case of error, 0 if the declaration is inproper and
1986 * 1 in case of success.
1987 */
1988static xmlSchemaAttributePtr
1989xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1990 xmlNodePtr node)
1991{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001992 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001993 xmlSchemaAttributePtr ret;
1994 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001995 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001996
1997 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1998 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001999 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002000 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002001
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002002 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2003 if (ref == NULL) {
2004 xmlSchemaPErr2(ctxt, node, child,
2005 XML_SCHEMAP_ATTR_NONAME_NOREF,
2006 "Attribute has no name nor ref\n", NULL, NULL);
2007 return (NULL);
2008 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002009 if (refNs == NULL)
2010 refNs = schema->targetNamespace;
2011 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2012 name = (const xmlChar *) buf;
2013 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2014 } else {
2015 const xmlChar *local, *ns;
2016
2017 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2018 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002019 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002020 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002021 return (NULL);
2022 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002023 ret->ref = ref;
2024 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002025 if ((ret->targetNamespace != NULL) &&
2026 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2027 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2028 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002029 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002030 if ((ret->typeName != NULL) && (ret->typeNs == NULL))
2031 ret->typeNs = schema->targetNamespace;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002032 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002033 child = node->children;
2034 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002035 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2036 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002037 }
2038 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002039 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2040 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002041 }
2042 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002043 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2044 "attribute %s has unexpected content\n", name,
2045 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002046 }
2047
2048 return (ret);
2049}
2050
2051/**
2052 * xmlSchemaParseAttributeGroup:
2053 * @ctxt: a schema validation context
2054 * @schema: the schema being built
2055 * @node: a subtree containing XML Schema informations
2056 *
2057 * parse a XML schema Attribute Group declaration
2058 * *WARNING* this interface is highly subject to change
2059 *
2060 * Returns the attribute group or NULL in case of error.
2061 */
2062static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002063xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2064 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002065{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002066 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002067 xmlSchemaAttributeGroupPtr ret;
2068 xmlSchemaAttributePtr last = NULL, attr;
2069 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002070 const xmlChar *oldcontainer;
2071 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002072
2073 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2074 return (NULL);
2075 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002076 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002077 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002078
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002079 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2080 if (ref == NULL) {
2081 xmlSchemaPErr2(ctxt, node, child,
2082 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2083 "AttributeGroup has no name nor ref\n", NULL,
2084 NULL);
2085 return (NULL);
2086 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002087 if (refNs == NULL)
2088 refNs = schema->targetNamespace;
2089 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2090 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002091 if (name == NULL) {
2092 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2093 return (NULL);
2094 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002095 }
2096 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2097 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002098 return (NULL);
2099 }
2100 ret->ref = ref;
2101 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002102 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002103 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002104 child = node->children;
2105 ctxt->container = name;
2106 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002107 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2108 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002109 }
2110 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002111 (IS_SCHEMA(child, "attributeGroup"))) {
2112 attr = NULL;
2113 if (IS_SCHEMA(child, "attribute")) {
2114 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2115 } else if (IS_SCHEMA(child, "attributeGroup")) {
2116 attr = (xmlSchemaAttributePtr)
2117 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2118 }
2119 if (attr != NULL) {
2120 if (last == NULL) {
2121 ret->attributes = attr;
2122 last = attr;
2123 } else {
2124 last->next = attr;
2125 last = attr;
2126 }
2127 }
2128 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002129 }
2130 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002131 TODO
2132 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 }
2134 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002135 xmlSchemaPErr2(ctxt, node, child,
2136 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2137 "attribute group %s has unexpected content\n", name,
2138 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002139 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002140 ctxt->container = oldcontainer;
2141 return (ret);
2142}
2143
2144/**
2145 * xmlSchemaParseElement:
2146 * @ctxt: a schema validation context
2147 * @schema: the schema being built
2148 * @node: a subtree containing XML Schema informations
2149 *
2150 * parse a XML schema Element declaration
2151 * *WARNING* this interface is highly subject to change
2152 *
2153 * Returns -1 in case of error, 0 if the declaration is inproper and
2154 * 1 in case of success.
2155 */
2156static xmlSchemaElementPtr
2157xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2158 xmlNodePtr node, int toplevel)
2159{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002160 const xmlChar *name, *fixed;
2161 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002162 xmlSchemaElementPtr ret;
2163 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002164 const xmlChar *oldcontainer;
2165 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002166
2167 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2168 return (NULL);
2169 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002170 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002171 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002172
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002173 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2174 if (ref == NULL) {
2175 xmlSchemaPErr2(ctxt, node, child,
2176 XML_SCHEMAP_ELEM_NONAME_NOREF,
2177 "Element has no name nor ref\n", NULL, NULL);
2178 return (NULL);
2179 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002180 if (refNs == NULL)
2181 refNs = schema->targetNamespace;
2182 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2183 name = (const xmlChar *) buf;
2184 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2185 } else {
2186 const xmlChar *local, *ns;
2187
2188 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2189 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002190 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002191 if (ret != NULL)
2192 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002193 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002194 return (NULL);
2195 }
2196 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2197 ret->ref = ref;
2198 ret->refNs = refNs;
2199 if (ref != NULL)
2200 ret->flags |= XML_SCHEMAS_ELEM_REF;
2201 if (toplevel)
2202 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2203 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2204 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2205 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2206 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2207 ctxt->container = name;
2208
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002209 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002210 ret->namedType =
2211 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002212 if ((ret->namedType != NULL) && (ret->namedTypeNs == NULL))
2213 ret->namedTypeNs = schema->targetNamespace;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002214 ret->substGroup =
2215 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2216 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002217 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002218 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2219 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002220
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002221 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002222 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002223 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2224 "Element %s has both default and fixed\n",
2225 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002226 } else if (fixed != NULL) {
2227 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002229 }
2230
2231 child = node->children;
2232 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002233 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2234 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002235 }
2236 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002237 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002238 child = child->next;
2239 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002240 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002241 child = child->next;
2242 }
2243 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002244 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2245 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002246 }
2247 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2249 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002250 }
2251
2252 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002253 return (ret);
2254}
2255
2256/**
2257 * xmlSchemaParseUnion:
2258 * @ctxt: a schema validation context
2259 * @schema: the schema being built
2260 * @node: a subtree containing XML Schema informations
2261 *
2262 * parse a XML schema Union definition
2263 * *WARNING* this interface is highly subject to change
2264 *
2265 * Returns -1 in case of error, 0 if the declaration is inproper and
2266 * 1 in case of success.
2267 */
2268static xmlSchemaTypePtr
2269xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002270 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002271{
2272 xmlSchemaTypePtr type, subtype, last = NULL;
2273 xmlNodePtr child = NULL;
2274 xmlChar name[30];
2275
2276 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2277 return (NULL);
2278
2279
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002280 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002281 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002282 if (type == NULL)
2283 return (NULL);
2284 type->node = node;
2285 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002286 type->id = xmlSchemaGetProp(ctxt, node, "id");
2287 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002288
2289 child = node->children;
2290 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002291 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2292 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002293 }
2294 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002295 subtype = (xmlSchemaTypePtr)
2296 xmlSchemaParseSimpleType(ctxt, schema, child);
2297 if (subtype != NULL) {
2298 if (last == NULL) {
2299 type->subtypes = subtype;
2300 last = subtype;
2301 } else {
2302 last->next = subtype;
2303 last = subtype;
2304 }
2305 last->next = NULL;
2306 }
2307 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002308 }
2309 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002310 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2311 "Union %s has unexpected content\n", type->name,
2312 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002313 }
2314 return (type);
2315}
2316
2317/**
2318 * xmlSchemaParseList:
2319 * @ctxt: a schema validation context
2320 * @schema: the schema being built
2321 * @node: a subtree containing XML Schema informations
2322 *
2323 * parse a XML schema List definition
2324 * *WARNING* this interface is highly subject to change
2325 *
2326 * Returns -1 in case of error, 0 if the declaration is inproper and
2327 * 1 in case of success.
2328 */
2329static xmlSchemaTypePtr
2330xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002331 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002332{
2333 xmlSchemaTypePtr type, subtype;
2334 xmlNodePtr child = NULL;
2335 xmlChar name[30];
2336
2337 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2338 return (NULL);
2339
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002340 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002341 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002342 if (type == NULL)
2343 return (NULL);
2344 type->node = node;
2345 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002346 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002347 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002348 if ((type->ref != NULL) && (type->refNs == NULL))
2349 type->refNs = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00002350
2351 child = node->children;
2352 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002353 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2354 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002355 }
2356 subtype = NULL;
2357 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002358 subtype = (xmlSchemaTypePtr)
2359 xmlSchemaParseSimpleType(ctxt, schema, child);
2360 child = child->next;
2361 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002362 }
2363 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002364 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2365 "List %s has unexpected content\n", type->name,
2366 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002367 }
2368 return (type);
2369}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002370
Daniel Veillard4255d502002-04-16 15:50:10 +00002371/**
2372 * xmlSchemaParseSimpleType:
2373 * @ctxt: a schema validation context
2374 * @schema: the schema being built
2375 * @node: a subtree containing XML Schema informations
2376 *
2377 * parse a XML schema Simple Type definition
2378 * *WARNING* this interface is highly subject to change
2379 *
2380 * Returns -1 in case of error, 0 if the declaration is inproper and
2381 * 1 in case of success.
2382 */
2383static xmlSchemaTypePtr
2384xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2385 xmlNodePtr node)
2386{
2387 xmlSchemaTypePtr type, subtype;
2388 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002389 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002390
2391 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2392 return (NULL);
2393
2394
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002395 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002396 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002397 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002398
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002399 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2400 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2401 } else {
2402 const xmlChar *local, *ns;
2403
2404 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2405 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002406 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002407 if (type == NULL)
2408 return (NULL);
2409 type->node = node;
2410 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002411 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002412
2413 child = node->children;
2414 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2416 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002417 }
2418 subtype = NULL;
2419 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002420 subtype = (xmlSchemaTypePtr)
2421 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2422 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002423 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002424 subtype = (xmlSchemaTypePtr)
2425 xmlSchemaParseList(ctxt, schema, child);
2426 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002427 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002428 subtype = (xmlSchemaTypePtr)
2429 xmlSchemaParseUnion(ctxt, schema, child);
2430 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002431 }
2432 type->subtypes = subtype;
2433 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002434 xmlSchemaPErr2(ctxt, node, child,
2435 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2436 "SimpleType %s has unexpected content\n",
2437 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002438 }
2439
2440 return (type);
2441}
2442
2443
2444/**
2445 * xmlSchemaParseGroup:
2446 * @ctxt: a schema validation context
2447 * @schema: the schema being built
2448 * @node: a subtree containing XML Schema informations
2449 *
2450 * parse a XML schema Group definition
2451 * *WARNING* this interface is highly subject to change
2452 *
2453 * Returns -1 in case of error, 0 if the declaration is inproper and
2454 * 1 in case of success.
2455 */
2456static xmlSchemaTypePtr
2457xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002458 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002459{
2460 xmlSchemaTypePtr type, subtype;
2461 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002462 const xmlChar *name;
2463 const xmlChar *ref = NULL, *refNs = NULL;
2464 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002465
2466 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2467 return (NULL);
2468
2469
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002470 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002471 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002472
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002473 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2474 if (ref == NULL) {
2475 xmlSchemaPErr2(ctxt, node, child,
2476 XML_SCHEMAP_GROUP_NONAME_NOREF,
2477 "Group has no name nor ref\n", NULL, NULL);
2478 return (NULL);
2479 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002480 if (refNs == NULL)
2481 refNs = schema->targetNamespace;
2482 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2483 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002484 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002485 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002486 if (type == NULL)
2487 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002488
Daniel Veillard4255d502002-04-16 15:50:10 +00002489 type->node = node;
2490 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002491 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002492 type->ref = ref;
2493 type->refNs = refNs;
2494 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2495 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2496
2497 child = node->children;
2498 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002499 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2500 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002501 }
2502 subtype = NULL;
2503 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002504 subtype = (xmlSchemaTypePtr)
2505 xmlSchemaParseAll(ctxt, schema, child);
2506 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002507 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002508 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2509 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002510 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002511 subtype = (xmlSchemaTypePtr)
2512 xmlSchemaParseSequence(ctxt, schema, child);
2513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002514 }
2515 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002516 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002517 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002518 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2519 "Group %s has unexpected content\n", type->name,
2520 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002521 }
2522
2523 return (type);
2524}
2525
2526/**
2527 * xmlSchemaParseAll:
2528 * @ctxt: a schema validation context
2529 * @schema: the schema being built
2530 * @node: a subtree containing XML Schema informations
2531 *
2532 * parse a XML schema All definition
2533 * *WARNING* this interface is highly subject to change
2534 *
2535 * Returns -1 in case of error, 0 if the declaration is inproper and
2536 * 1 in case of success.
2537 */
2538static xmlSchemaTypePtr
2539xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002540 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002541{
2542 xmlSchemaTypePtr type, subtype, last = NULL;
2543 xmlNodePtr child = NULL;
2544 xmlChar name[30];
2545
2546 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2547 return (NULL);
2548
2549
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002550 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002551 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002552 if (type == NULL)
2553 return (NULL);
2554 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002555 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002556 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002557 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002558 if (type->minOccurs > 1)
2559 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2560 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002561 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002562 if (type->maxOccurs > 1)
2563 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2564 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002565
2566 child = node->children;
2567 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002568 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2569 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002570 }
2571 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002572 subtype = (xmlSchemaTypePtr)
2573 xmlSchemaParseElement(ctxt, schema, child, 0);
2574 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002575 if (subtype->minOccurs > 1)
2576 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2577 "invalid value for minOccurs (must be 0 or 1)\n",
2578 NULL, NULL);
2579 if (subtype->maxOccurs > 1)
2580 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2581 "invalid value for maxOccurs (must be 0 or 1)\n",
2582 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002583 if (last == NULL) {
2584 type->subtypes = subtype;
2585 last = subtype;
2586 } else {
2587 last->next = subtype;
2588 last = subtype;
2589 }
2590 last->next = NULL;
2591 }
2592 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002593 }
2594 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002595 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2596 "All %s has unexpected content\n", type->name,
2597 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002598 }
2599
2600 return (type);
2601}
2602
2603/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002604 * xmlSchemaImportSchema
2605 *
2606 * @ctxt: a schema validation context
2607 * @schemaLocation: an URI defining where to find the imported schema
2608 *
2609 * import a XML schema
2610 * *WARNING* this interface is highly subject to change
2611 *
2612 * Returns -1 in case of error and 1 in case of success.
2613 */
2614static xmlSchemaImportPtr
2615xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2616 const xmlChar *schemaLocation)
2617{
2618 xmlSchemaImportPtr import;
2619 xmlSchemaParserCtxtPtr newctxt;
2620
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002621 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002622 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002623 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002624 NULL);
2625 return (NULL);
2626 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002627 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2628 /* Keep the same dictionnary for parsing, really */
2629 xmlDictReference(ctxt->dict);
2630 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002631 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002632 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2633
Daniel Veillard1d913862003-11-21 00:28:39 +00002634 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2635 ctxt->userData);
2636
2637 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2638 if (import == NULL) {
2639 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2640 NULL);
2641 xmlSchemaFreeParserCtxt(newctxt);
2642 return (NULL);
2643 }
2644
2645 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002646 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002647 import->schema = xmlSchemaParse(newctxt);
2648
2649 if (import->schema == NULL) {
2650 /* FIXME use another error enum here ? */
2651 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2652 "failed to import schema at location %s\n",
2653 schemaLocation, NULL);
2654
2655 xmlSchemaFreeParserCtxt(newctxt);
2656 if (import->schemaLocation != NULL)
2657 xmlFree((xmlChar *)import->schemaLocation);
2658 xmlFree(import);
2659 return NULL;
2660 }
2661
2662 xmlSchemaFreeParserCtxt(newctxt);
2663 return import;
2664}
2665
2666
2667/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002668 * xmlSchemaParseImport:
2669 * @ctxt: a schema validation context
2670 * @schema: the schema being built
2671 * @node: a subtree containing XML Schema informations
2672 *
2673 * parse a XML schema Import definition
2674 * *WARNING* this interface is highly subject to change
2675 *
2676 * Returns -1 in case of error, 0 if the declaration is inproper and
2677 * 1 in case of success.
2678 */
2679static int
2680xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002681 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002682{
2683 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002684 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002685 const xmlChar *namespace;
2686 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002687 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002688 xmlURIPtr check;
2689
Daniel Veillard1d913862003-11-21 00:28:39 +00002690
Daniel Veillard5a872412002-05-22 06:40:27 +00002691 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2692 return (-1);
2693
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002694 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002695 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002696 check = xmlParseURI((const char *) namespace);
2697 if (check == NULL) {
2698 xmlSchemaPErr2(ctxt, node, child,
2699 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2700 "Import namespace attribute is not an URI: %s\n",
2701 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002702 return (-1);
2703 } else {
2704 xmlFreeURI(check);
2705 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002706 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002707 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002708 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002709 xmlChar *base = NULL;
2710 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002711 check = xmlParseURI((const char *) schemaLocation);
2712 if (check == NULL) {
2713 xmlSchemaPErr2(ctxt, node, child,
2714 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2715 "Import schemaLocation attribute is not an URI: %s\n",
2716 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002717 return (-1);
2718 } else {
2719 xmlFreeURI(check);
2720 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002721 base = xmlNodeGetBase(node->doc, node);
2722 if (base == NULL) {
2723 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2724 } else {
2725 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002726 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002727 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002728 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002729 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2730 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002731 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002732 }
2733 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002734 schema->schemasImports = xmlHashCreate(10);
2735 if (schema->schemasImports == NULL) {
2736 xmlSchemaPErr2(ctxt, node, child,
2737 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2738 "Internal: failed to build import table\n",
2739 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002740 return (-1);
2741 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002742 }
2743 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002744 import = xmlHashLookup(schema->schemasImports,
2745 XML_SCHEMAS_DEFAULT_NAMESPACE);
2746 if (import != NULL)
2747 previous = import->schemaLocation;
2748 else
2749 previous = NULL;
2750
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002751 if (schemaLocation != NULL) {
2752 if (previous != NULL) {
2753 if (!xmlStrEqual(schemaLocation, previous)) {
2754 xmlSchemaPErr2(ctxt, node, child,
2755 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2756 "Redefining import for default namespace with a different URI: %s\n",
2757 schemaLocation, NULL);
2758 }
2759 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002760 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2761 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002762 return (-1);
2763 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 xmlHashAddEntry(schema->schemasImports,
2765 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002766 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002767 }
2768 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002769 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002770 import = xmlHashLookup(schema->schemasImports, namespace);
2771 if (import != NULL)
2772 previous = import->schemaLocation;
2773 else
2774 previous = NULL;
2775
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002776 if (schemaLocation != NULL) {
2777 if (previous != NULL) {
2778 if (!xmlStrEqual(schemaLocation, previous)) {
2779 xmlSchemaPErr2(ctxt, node, child,
2780 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2781 "Redefining import for namespace %s with a different URI: %s\n",
2782 namespace, schemaLocation);
2783 }
2784 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002785 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2786 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002787 return (-1);
2788 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002789 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002790 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002791 }
2792 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002793 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002794
2795 child = node->children;
2796 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002797 /*
2798 * the annotations here are simply discarded ...
2799 */
2800 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002801 }
2802 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002803 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2804 "Import has unexpected content\n", NULL, NULL);
2805 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002806 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002807 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002808}
2809
2810/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002811 * xmlSchemaCleanupDoc:
2812 * @ctxt: a schema validation context
2813 * @node: the root of the document.
2814 *
2815 * removes unwanted nodes in a schemas document tree
2816 */
2817static void
2818xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
2819{
2820 xmlNodePtr delete, cur;
2821
2822 if ((ctxt == NULL) || (root == NULL)) return;
2823
2824 /*
2825 * Remove all the blank text nodes
2826 */
2827 delete = NULL;
2828 cur = root;
2829 while (cur != NULL) {
2830 if (delete != NULL) {
2831 xmlUnlinkNode(delete);
2832 xmlFreeNode(delete);
2833 delete = NULL;
2834 }
2835 if (cur->type == XML_TEXT_NODE) {
2836 if (IS_BLANK_NODE(cur)) {
2837 if (xmlNodeGetSpacePreserve(cur) != 1) {
2838 delete = cur;
2839 }
2840 }
2841 } else if ((cur->type != XML_ELEMENT_NODE) &&
2842 (cur->type != XML_CDATA_SECTION_NODE)) {
2843 delete = cur;
2844 goto skip_children;
2845 }
2846
2847 /*
2848 * Skip to next node
2849 */
2850 if (cur->children != NULL) {
2851 if ((cur->children->type != XML_ENTITY_DECL) &&
2852 (cur->children->type != XML_ENTITY_REF_NODE) &&
2853 (cur->children->type != XML_ENTITY_NODE)) {
2854 cur = cur->children;
2855 continue;
2856 }
2857 }
2858 skip_children:
2859 if (cur->next != NULL) {
2860 cur = cur->next;
2861 continue;
2862 }
2863
2864 do {
2865 cur = cur->parent;
2866 if (cur == NULL)
2867 break;
2868 if (cur == root) {
2869 cur = NULL;
2870 break;
2871 }
2872 if (cur->next != NULL) {
2873 cur = cur->next;
2874 break;
2875 }
2876 } while (cur != NULL);
2877 }
2878 if (delete != NULL) {
2879 xmlUnlinkNode(delete);
2880 xmlFreeNode(delete);
2881 delete = NULL;
2882 }
2883}
2884
2885/**
2886 * xmlSchemaParseSchemaTopLevel:
2887 * @ctxt: a schema validation context
2888 * @schema: the schemas
2889 * @nodes: the list of top level nodes
2890 *
2891 * Returns the internal XML Schema structure built from the resource or
2892 * NULL in case of error
2893 */
2894static void
2895xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
2896 xmlSchemaPtr schema, xmlNodePtr nodes)
2897{
2898 xmlNodePtr child;
2899 xmlSchemaAnnotPtr annot;
2900
2901 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
2902 return;
2903
2904 child = nodes;
2905 while ((IS_SCHEMA(child, "include")) ||
2906 (IS_SCHEMA(child, "import")) ||
2907 (IS_SCHEMA(child, "redefine")) ||
2908 (IS_SCHEMA(child, "annotation"))) {
2909 if (IS_SCHEMA(child, "annotation")) {
2910 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2911 if (schema->annot == NULL)
2912 schema->annot = annot;
2913 else
2914 xmlSchemaFreeAnnot(annot);
2915 } else if (IS_SCHEMA(child, "import")) {
2916 xmlSchemaParseImport(ctxt, schema, child);
2917 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002918 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002919 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002920 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002921 } else if (IS_SCHEMA(child, "redefine")) {
2922 TODO
2923 }
2924 child = child->next;
2925 }
2926 while (child != NULL) {
2927 if (IS_SCHEMA(child, "complexType")) {
2928 xmlSchemaParseComplexType(ctxt, schema, child);
2929 child = child->next;
2930 } else if (IS_SCHEMA(child, "simpleType")) {
2931 xmlSchemaParseSimpleType(ctxt, schema, child);
2932 child = child->next;
2933 } else if (IS_SCHEMA(child, "element")) {
2934 xmlSchemaParseElement(ctxt, schema, child, 1);
2935 child = child->next;
2936 } else if (IS_SCHEMA(child, "attribute")) {
2937 xmlSchemaParseAttribute(ctxt, schema, child);
2938 child = child->next;
2939 } else if (IS_SCHEMA(child, "attributeGroup")) {
2940 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2941 child = child->next;
2942 } else if (IS_SCHEMA(child, "group")) {
2943 xmlSchemaParseGroup(ctxt, schema, child);
2944 child = child->next;
2945 } else if (IS_SCHEMA(child, "notation")) {
2946 xmlSchemaParseNotation(ctxt, schema, child);
2947 child = child->next;
2948 } else {
2949 xmlSchemaPErr2(ctxt, NULL, child,
2950 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
2951 "Schemas: unexpected element %s here \n",
2952 child->name, NULL);
2953 child = child->next;
2954 }
2955 while (IS_SCHEMA(child, "annotation")) {
2956 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2957 if (schema->annot == NULL)
2958 schema->annot = annot;
2959 else
2960 xmlSchemaFreeAnnot(annot);
2961 child = child->next;
2962 }
2963 }
2964}
2965
2966/**
2967 * xmlSchemaParseInclude:
2968 * @ctxt: a schema validation context
2969 * @schema: the schema being built
2970 * @node: a subtree containing XML Schema informations
2971 *
2972 * parse a XML schema Include definition
2973 *
2974 * Returns -1 in case of error, 0 if the declaration is inproper and
2975 * 1 in case of success.
2976 */
2977static int
2978xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2979 xmlNodePtr node)
2980{
2981 xmlNodePtr child = NULL;
2982 const xmlChar *schemaLocation;
2983 xmlURIPtr check;
2984 xmlDocPtr doc;
2985 xmlNodePtr root;
2986 xmlSchemaIncludePtr include;
2987
2988
2989 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2990 return (-1);
2991
2992 /*
2993 * Preliminary step, extract the URI-Reference for the include and
2994 * make an URI from the base.
2995 */
2996 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
2997 if (schemaLocation != NULL) {
2998 xmlChar *base = NULL;
2999 xmlChar *URI = NULL;
3000 check = xmlParseURI((const char *) schemaLocation);
3001 if (check == NULL) {
3002 xmlSchemaPErr2(ctxt, node, child,
3003 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3004 "Include schemaLocation attribute is not an URI: %s\n",
3005 schemaLocation, NULL);
3006 return (-1);
3007 } else {
3008 xmlFreeURI(check);
3009 }
3010 base = xmlNodeGetBase(node->doc, node);
3011 if (base == NULL) {
3012 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3013 } else {
3014 URI = xmlBuildURI(schemaLocation, base);
3015 xmlFree(base);
3016 }
3017 if (URI != NULL) {
3018 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3019 xmlFree(URI);
3020 }
3021 } else {
3022 xmlSchemaPErr2(ctxt, node, child,
3023 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3024 "Include schemaLocation attribute missing\n",
3025 NULL, NULL);
3026 return (-1);
3027 }
3028
3029 child = node->children;
3030 while (IS_SCHEMA(child, "annotation")) {
3031 /*
3032 * the annotations here are simply discarded ...
3033 */
3034 child = child->next;
3035 }
3036 if (child != NULL) {
3037 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3038 "Include has unexpected content\n", NULL, NULL);
3039 return (-1);
3040 }
3041
3042 /*
3043 * First step is to parse the input document into an DOM/Infoset
3044 */
3045 doc = xmlReadFile((const char *) schemaLocation, NULL,
3046 SCHEMAS_PARSE_OPTIONS);
3047 if (doc == NULL) {
3048 xmlSchemaPErr(ctxt, NULL,
3049 XML_SCHEMAP_FAILED_LOAD,
3050 "xmlSchemaParse: could not load %s\n",
3051 ctxt->URL, NULL);
3052 return(-1);
3053 }
3054
3055 /*
3056 * Then extract the root of the schema
3057 */
3058 root = xmlDocGetRootElement(doc);
3059 if (root == NULL) {
3060 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3061 XML_SCHEMAP_NOROOT,
3062 "schemas %s has no root", schemaLocation, NULL);
3063 xmlFreeDoc(doc);
3064 return (-1);
3065 }
3066
3067 /*
3068 * Remove all the blank text nodes
3069 */
3070 xmlSchemaCleanupDoc(ctxt, root);
3071
3072 /*
3073 * Check the schemas top level element
3074 */
3075 if (!IS_SCHEMA(root, "schema")) {
3076 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3077 XML_SCHEMAP_NOT_SCHEMA,
3078 "File %s is not a schemas", schemaLocation, NULL);
3079 xmlFreeDoc(doc);
3080 return (-1);
3081 }
3082
3083 /*
3084 * register the include
3085 */
3086 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3087 if (include == NULL) {
3088 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3089 xmlFreeDoc(doc);
3090 return (-1);
3091 }
3092
3093 memset(include, 0, sizeof(xmlSchemaInclude));
3094 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3095 include->doc = doc;
3096 include->next = schema->includes;
3097 schema->includes = include;
3098
3099
3100 /*
3101 * parse the declarations in the included file like if they
3102 * were in the original file.
3103 */
3104 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3105
3106 return (1);
3107}
3108
3109/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003110 * xmlSchemaParseChoice:
3111 * @ctxt: a schema validation context
3112 * @schema: the schema being built
3113 * @node: a subtree containing XML Schema informations
3114 *
3115 * parse a XML schema Choice definition
3116 * *WARNING* this interface is highly subject to change
3117 *
3118 * Returns -1 in case of error, 0 if the declaration is inproper and
3119 * 1 in case of success.
3120 */
3121static xmlSchemaTypePtr
3122xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003123 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003124{
3125 xmlSchemaTypePtr type, subtype, last = NULL;
3126 xmlNodePtr child = NULL;
3127 xmlChar name[30];
3128
3129 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3130 return (NULL);
3131
3132
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003133 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003134 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003135 if (type == NULL)
3136 return (NULL);
3137 type->node = node;
3138 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003139 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003140 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3141 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3142
3143 child = node->children;
3144 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003145 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3146 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003147 }
3148 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003149 (IS_SCHEMA(child, "group")) ||
3150 (IS_SCHEMA(child, "any")) ||
3151 (IS_SCHEMA(child, "choice")) ||
3152 (IS_SCHEMA(child, "sequence"))) {
3153 subtype = NULL;
3154 if (IS_SCHEMA(child, "element")) {
3155 subtype = (xmlSchemaTypePtr)
3156 xmlSchemaParseElement(ctxt, schema, child, 0);
3157 } else if (IS_SCHEMA(child, "group")) {
3158 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3159 } else if (IS_SCHEMA(child, "any")) {
3160 subtype = xmlSchemaParseAny(ctxt, schema, child);
3161 } else if (IS_SCHEMA(child, "sequence")) {
3162 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3163 } else if (IS_SCHEMA(child, "choice")) {
3164 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3165 }
3166 if (subtype != NULL) {
3167 if (last == NULL) {
3168 type->subtypes = subtype;
3169 last = subtype;
3170 } else {
3171 last->next = subtype;
3172 last = subtype;
3173 }
3174 last->next = NULL;
3175 }
3176 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 }
3178 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003179 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3180 "Choice %s has unexpected content\n", type->name,
3181 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003182 }
3183
3184 return (type);
3185}
3186
3187/**
3188 * xmlSchemaParseSequence:
3189 * @ctxt: a schema validation context
3190 * @schema: the schema being built
3191 * @node: a subtree containing XML Schema informations
3192 *
3193 * parse a XML schema Sequence definition
3194 * *WARNING* this interface is highly subject to change
3195 *
3196 * Returns -1 in case of error, 0 if the declaration is inproper and
3197 * 1 in case of success.
3198 */
3199static xmlSchemaTypePtr
3200xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003201 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003202{
3203 xmlSchemaTypePtr type, subtype, last = NULL;
3204 xmlNodePtr child = NULL;
3205 xmlChar name[30];
3206
3207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3208 return (NULL);
3209
3210
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003212 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 if (type == NULL)
3214 return (NULL);
3215 type->node = node;
3216 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003217 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3219 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3220
3221 child = node->children;
3222 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003223 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003225 }
3226 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003227 (IS_SCHEMA(child, "group")) ||
3228 (IS_SCHEMA(child, "any")) ||
3229 (IS_SCHEMA(child, "choice")) ||
3230 (IS_SCHEMA(child, "sequence"))) {
3231 subtype = NULL;
3232 if (IS_SCHEMA(child, "element")) {
3233 subtype = (xmlSchemaTypePtr)
3234 xmlSchemaParseElement(ctxt, schema, child, 0);
3235 } else if (IS_SCHEMA(child, "group")) {
3236 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3237 } else if (IS_SCHEMA(child, "any")) {
3238 subtype = xmlSchemaParseAny(ctxt, schema, child);
3239 } else if (IS_SCHEMA(child, "choice")) {
3240 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3241 } else if (IS_SCHEMA(child, "sequence")) {
3242 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3243 }
3244 if (subtype != NULL) {
3245 if (last == NULL) {
3246 type->subtypes = subtype;
3247 last = subtype;
3248 } else {
3249 last->next = subtype;
3250 last = subtype;
3251 }
3252 last->next = NULL;
3253 }
3254 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003255 }
3256 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003257 xmlSchemaPErr2(ctxt, node, child,
3258 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3259 "Sequence %s has unexpected content\n", type->name,
3260 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003261 }
3262
3263 return (type);
3264}
3265
3266/**
3267 * xmlSchemaParseRestriction:
3268 * @ctxt: a schema validation context
3269 * @schema: the schema being built
3270 * @node: a subtree containing XML Schema informations
3271 * @simple: is that part of a simple type.
3272 *
3273 * parse a XML schema Restriction definition
3274 * *WARNING* this interface is highly subject to change
3275 *
3276 * Returns the type definition or NULL in case of error
3277 */
3278static xmlSchemaTypePtr
3279xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3280 xmlNodePtr node, int simple)
3281{
3282 xmlSchemaTypePtr type, subtype;
3283 xmlSchemaFacetPtr facet, lastfacet = NULL;
3284 xmlNodePtr child = NULL;
3285 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003286 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003287
3288 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3289 return (NULL);
3290
3291 oldcontainer = ctxt->container;
3292
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003293 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003294 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003295 if (type == NULL)
3296 return (NULL);
3297 type->node = node;
3298 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003299 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003300 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3301 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003302 xmlSchemaPErr2(ctxt, node, child,
3303 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3304 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003305 }
3306 ctxt->container = name;
3307
3308 child = node->children;
3309 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003310 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3311 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003312 }
3313 subtype = NULL;
3314
3315 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003316 subtype = (xmlSchemaTypePtr)
3317 xmlSchemaParseAll(ctxt, schema, child);
3318 child = child->next;
3319 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003320 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003321 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3322 child = child->next;
3323 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003324 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003325 subtype = (xmlSchemaTypePtr)
3326 xmlSchemaParseSequence(ctxt, schema, child);
3327 child = child->next;
3328 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003329 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003330 subtype = (xmlSchemaTypePtr)
3331 xmlSchemaParseGroup(ctxt, schema, child);
3332 child = child->next;
3333 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003334 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003335 if (IS_SCHEMA(child, "simpleType")) {
3336 subtype = (xmlSchemaTypePtr)
3337 xmlSchemaParseSimpleType(ctxt, schema, child);
3338 child = child->next;
3339 type->baseType = subtype;
3340 }
3341 /*
3342 * Facets
3343 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003344 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003345 (IS_SCHEMA(child, "minExclusive")) ||
3346 (IS_SCHEMA(child, "maxInclusive")) ||
3347 (IS_SCHEMA(child, "maxExclusive")) ||
3348 (IS_SCHEMA(child, "totalDigits")) ||
3349 (IS_SCHEMA(child, "fractionDigits")) ||
3350 (IS_SCHEMA(child, "pattern")) ||
3351 (IS_SCHEMA(child, "enumeration")) ||
3352 (IS_SCHEMA(child, "whiteSpace")) ||
3353 (IS_SCHEMA(child, "length")) ||
3354 (IS_SCHEMA(child, "maxLength")) ||
3355 (IS_SCHEMA(child, "minLength"))) {
3356 facet = xmlSchemaParseFacet(ctxt, schema, child);
3357 if (facet != NULL) {
3358 if (lastfacet == NULL) {
3359 type->facets = facet;
3360 lastfacet = facet;
3361 } else {
3362 lastfacet->next = facet;
3363 lastfacet = facet;
3364 }
3365 lastfacet->next = NULL;
3366 }
3367 child = child->next;
3368 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003369 }
3370 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3371 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003372 xmlSchemaPErr2(ctxt, node, child,
3373 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3374 "Restriction %s has unexpected content\n",
3375 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003376 }
3377 ctxt->container = oldcontainer;
3378 return (type);
3379}
3380
3381/**
3382 * xmlSchemaParseExtension:
3383 * @ctxt: a schema validation context
3384 * @schema: the schema being built
3385 * @node: a subtree containing XML Schema informations
3386 *
3387 * parse a XML schema Extension definition
3388 * *WARNING* this interface is highly subject to change
3389 *
3390 * Returns the type definition or NULL in case of error
3391 */
3392static xmlSchemaTypePtr
3393xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003394 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003395{
3396 xmlSchemaTypePtr type, subtype;
3397 xmlNodePtr child = NULL;
3398 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003399 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003400
3401 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3402 return (NULL);
3403
3404 oldcontainer = ctxt->container;
3405
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003406 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003407 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 if (type == NULL)
3409 return (NULL);
3410 type->node = node;
3411 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003412 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003413 ctxt->container = name;
3414
3415 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3416 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003417 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3418 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003419 }
3420 child = node->children;
3421 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003422 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3423 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003424 }
3425 subtype = NULL;
3426
3427 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003428 subtype = xmlSchemaParseAll(ctxt, schema, child);
3429 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003430 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003431 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3432 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003433 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003434 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3435 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003436 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003437 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3438 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003439 }
3440 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003441 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003442 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3443 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003444 xmlSchemaPErr2(ctxt, node, child,
3445 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3446 "Extension %s has unexpected content\n", type->name,
3447 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003448 }
3449 ctxt->container = oldcontainer;
3450 return (type);
3451}
3452
3453/**
3454 * xmlSchemaParseSimpleContent:
3455 * @ctxt: a schema validation context
3456 * @schema: the schema being built
3457 * @node: a subtree containing XML Schema informations
3458 *
3459 * parse a XML schema SimpleContent definition
3460 * *WARNING* this interface is highly subject to change
3461 *
3462 * Returns the type definition or NULL in case of error
3463 */
3464static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003465xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3466 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003467{
3468 xmlSchemaTypePtr type, subtype;
3469 xmlNodePtr child = NULL;
3470 xmlChar name[30];
3471
3472 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3473 return (NULL);
3474
3475
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003476 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003477 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003478 if (type == NULL)
3479 return (NULL);
3480 type->node = node;
3481 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003482 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003483
3484 child = node->children;
3485 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003486 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3487 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003488 }
3489 subtype = NULL;
3490 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003491 subtype = (xmlSchemaTypePtr)
3492 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3493 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003495 subtype = (xmlSchemaTypePtr)
3496 xmlSchemaParseExtension(ctxt, schema, child);
3497 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003498 }
3499 type->subtypes = subtype;
3500 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003501 xmlSchemaPErr2(ctxt, node, child,
3502 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3503 "SimpleContent %s has unexpected content\n",
3504 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003505 }
3506 return (type);
3507}
3508
3509/**
3510 * xmlSchemaParseComplexContent:
3511 * @ctxt: a schema validation context
3512 * @schema: the schema being built
3513 * @node: a subtree containing XML Schema informations
3514 *
3515 * parse a XML schema ComplexContent definition
3516 * *WARNING* this interface is highly subject to change
3517 *
3518 * Returns the type definition or NULL in case of error
3519 */
3520static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003521xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3522 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003523{
3524 xmlSchemaTypePtr type, subtype;
3525 xmlNodePtr child = NULL;
3526 xmlChar name[30];
3527
3528 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3529 return (NULL);
3530
3531
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003532 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003533 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003534 if (type == NULL)
3535 return (NULL);
3536 type->node = node;
3537 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003538 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003539
3540 child = node->children;
3541 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003542 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3543 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003544 }
3545 subtype = NULL;
3546 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003547 subtype = (xmlSchemaTypePtr)
3548 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3549 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003550 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003551 subtype = (xmlSchemaTypePtr)
3552 xmlSchemaParseExtension(ctxt, schema, child);
3553 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003554 }
3555 type->subtypes = subtype;
3556 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003557 xmlSchemaPErr2(ctxt, node, child,
3558 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3559 "ComplexContent %s has unexpected content\n",
3560 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003561 }
3562 return (type);
3563}
3564
3565/**
3566 * xmlSchemaParseComplexType:
3567 * @ctxt: a schema validation context
3568 * @schema: the schema being built
3569 * @node: a subtree containing XML Schema informations
3570 *
3571 * parse a XML schema Complex Type definition
3572 * *WARNING* this interface is highly subject to change
3573 *
3574 * Returns the type definition or NULL in case of error
3575 */
3576static xmlSchemaTypePtr
3577xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3578 xmlNodePtr node)
3579{
3580 xmlSchemaTypePtr type, subtype;
3581 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003582 const xmlChar *name;
3583 const xmlChar *oldcontainer;
3584 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003585
3586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3587 return (NULL);
3588
3589 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003590 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003591 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003592
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003593 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3594 name = (const xmlChar *)buf;
3595 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3596 } else {
3597 const xmlChar *local, *ns;
3598
3599 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3600 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003601 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003603 return (NULL);
3604 }
3605 type->node = node;
3606 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003607 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003608 ctxt->container = name;
3609
3610 child = node->children;
3611 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003612 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3613 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 }
3615 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003616 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3617 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003619 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3620 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003622 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003623
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624 if (IS_SCHEMA(child, "all")) {
3625 subtype = xmlSchemaParseAll(ctxt, schema, child);
3626 child = child->next;
3627 } else if (IS_SCHEMA(child, "choice")) {
3628 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3629 child = child->next;
3630 } else if (IS_SCHEMA(child, "sequence")) {
3631 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3632 child = child->next;
3633 } else if (IS_SCHEMA(child, "group")) {
3634 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3635 child = child->next;
3636 }
3637 if (subtype != NULL)
3638 type->subtypes = subtype;
3639 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003640 }
3641 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003642 xmlSchemaPErr2(ctxt, node, child,
3643 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3644 "ComplexType %s has unexpected content\n",
3645 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003646 }
3647 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 return (type);
3649}
3650
Daniel Veillard4255d502002-04-16 15:50:10 +00003651/**
3652 * xmlSchemaParseSchema:
3653 * @ctxt: a schema validation context
3654 * @node: a subtree containing XML Schema informations
3655 *
3656 * parse a XML schema definition from a node set
3657 * *WARNING* this interface is highly subject to change
3658 *
3659 * Returns the internal XML Schema structure built from the resource or
3660 * NULL in case of error
3661 */
3662static xmlSchemaPtr
3663xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3664{
3665 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003666 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003667 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003668 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003669
3670 if ((ctxt == NULL) || (node == NULL))
3671 return (NULL);
3672
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003673 nberrors = ctxt->nberrors;
3674 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003675 if (IS_SCHEMA(node, "schema")) {
3676 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003677 if (schema == NULL)
3678 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003679 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3680 if (val != NULL) {
3681 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3682 } else {
3683 schema->targetNamespace = NULL;
3684 }
3685 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3686 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3687 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 if (val != NULL) {
3689 if (xmlStrEqual(val, BAD_CAST "qualified"))
3690 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3691 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3692 xmlSchemaPErr2(ctxt, node, child,
3693 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3694 "Invalid value %s for elementFormDefault\n",
3695 val, NULL);
3696 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003697 } else {
3698 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3699 }
3700 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003701 if (val != NULL) {
3702 if (xmlStrEqual(val, BAD_CAST "qualified"))
3703 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3704 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3705 xmlSchemaPErr2(ctxt, node, child,
3706 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3707 "Invalid value %s for attributeFormDefault\n",
3708 val, NULL);
3709 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003710 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003711
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003712 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
3713 } else {
3714 xmlDocPtr doc;
3715
3716 doc = node->doc;
3717
3718 if ((doc != NULL) && (doc->URL != NULL)) {
3719 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3720 XML_SCHEMAP_NOT_SCHEMA,
3721 "File %s is not a schemas", doc->URL, NULL);
3722 } else {
3723 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3724 XML_SCHEMAP_NOT_SCHEMA,
3725 "File is not a schemas", NULL, NULL);
3726 }
3727 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003729 if (ctxt->nberrors != 0) {
3730 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003731 xmlSchemaFree(schema);
3732 schema = NULL;
3733 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003734 }
3735 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003736#ifdef DEBUG
3737 if (schema == NULL)
3738 xmlGenericError(xmlGenericErrorContext,
3739 "xmlSchemaParse() failed\n");
3740#endif
3741
3742 return (schema);
3743}
3744
3745/************************************************************************
3746 * *
3747 * Validating using Schemas *
3748 * *
3749 ************************************************************************/
3750
3751/************************************************************************
3752 * *
3753 * Reading/Writing Schemas *
3754 * *
3755 ************************************************************************/
3756
3757/**
3758 * xmlSchemaNewParserCtxt:
3759 * @URL: the location of the schema
3760 *
3761 * Create an XML Schemas parse context for that file/resource expected
3762 * to contain an XML Schemas file.
3763 *
3764 * Returns the parser context or NULL in case of error
3765 */
3766xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003767xmlSchemaNewParserCtxt(const char *URL)
3768{
Daniel Veillard4255d502002-04-16 15:50:10 +00003769 xmlSchemaParserCtxtPtr ret;
3770
3771 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003772 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003773
3774 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3775 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003776 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3777 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003778 return (NULL);
3779 }
3780 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003781 ret->dict = xmlDictCreate();
3782 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003783 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 return (ret);
3785}
3786
3787/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003788 * xmlSchemaNewMemParserCtxt:
3789 * @buffer: a pointer to a char array containing the schemas
3790 * @size: the size of the array
3791 *
3792 * Create an XML Schemas parse context for that memory buffer expected
3793 * to contain an XML Schemas file.
3794 *
3795 * Returns the parser context or NULL in case of error
3796 */
3797xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003798xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3799{
Daniel Veillard6045c902002-10-09 21:13:59 +00003800 xmlSchemaParserCtxtPtr ret;
3801
3802 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003803 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003804
3805 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3806 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003807 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3808 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003809 return (NULL);
3810 }
3811 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3812 ret->buffer = buffer;
3813 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003814 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00003815 return (ret);
3816}
3817
3818/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003819 * xmlSchemaNewDocParserCtxt:
3820 * @doc: a preparsed document tree
3821 *
3822 * Create an XML Schemas parse context for that document.
3823 * NB. The document may be modified during the parsing process.
3824 *
3825 * Returns the parser context or NULL in case of error
3826 */
3827xmlSchemaParserCtxtPtr
3828xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3829{
3830 xmlSchemaParserCtxtPtr ret;
3831
3832 if (doc == NULL)
3833 return (NULL);
3834
3835 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3836 if (ret == NULL) {
3837 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3838 NULL);
3839 return (NULL);
3840 }
3841 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3842 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003843 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00003844 /* The application has responsibility for the document */
3845 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00003846
3847 return (ret);
3848}
3849
3850/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003851 * xmlSchemaFreeParserCtxt:
3852 * @ctxt: the schema parser context
3853 *
3854 * Free the resources associated to the schema parser context
3855 */
3856void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003857xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3858{
Daniel Veillard4255d502002-04-16 15:50:10 +00003859 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003860 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00003861 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003862 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003863 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003864 xmlFree(ctxt);
3865}
3866
3867/************************************************************************
3868 * *
3869 * Building the content models *
3870 * *
3871 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003872
Daniel Veillard4255d502002-04-16 15:50:10 +00003873/**
3874 * xmlSchemaBuildAContentModel:
3875 * @type: the schema type definition
3876 * @ctxt: the schema parser context
3877 * @name: the element name whose content is being built
3878 *
3879 * Generate the automata sequence needed for that type
3880 */
3881static void
3882xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003883 xmlSchemaParserCtxtPtr ctxt,
3884 const xmlChar * name)
3885{
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003887 xmlGenericError(xmlGenericErrorContext,
3888 "Found unexpected type = NULL in %s content model\n",
3889 name);
3890 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003891 }
3892 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 case XML_SCHEMA_TYPE_ANY:
3894 /* TODO : handle the namespace too */
3895 /* TODO : make that a specific transition type */
3896 TODO ctxt->state =
3897 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3898 BAD_CAST "*", NULL);
3899 break;
3900 case XML_SCHEMA_TYPE_ELEMENT:{
3901 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003902
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003903 /* TODO : handle the namespace too */
3904 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003905
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003906 if (elem->maxOccurs >= UNBOUNDED) {
3907 if (elem->minOccurs > 1) {
3908 xmlAutomataStatePtr tmp;
3909 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003910
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003911 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3912 oldstate,
3913 NULL);
3914 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003915
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003916 counter = xmlAutomataNewCounter(ctxt->am,
3917 elem->minOccurs -
3918 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003919
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003920 if (elem->refDecl != NULL) {
3921 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3922 elem->refDecl,
3923 ctxt,
3924 elem->refDecl->
3925 name);
3926 } else {
3927 ctxt->state =
3928 xmlAutomataNewTransition(ctxt->am,
3929 ctxt->state, NULL,
3930 elem->name, type);
3931 }
3932 tmp = ctxt->state;
3933 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3934 counter);
3935 ctxt->state =
3936 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3937 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003938
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003939 } else {
3940 if (elem->refDecl != NULL) {
3941 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3942 elem->refDecl,
3943 ctxt,
3944 elem->refDecl->
3945 name);
3946 } else {
3947 ctxt->state =
3948 xmlAutomataNewTransition(ctxt->am,
3949 ctxt->state, NULL,
3950 elem->name, type);
3951 }
3952 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3953 oldstate);
3954 if (elem->minOccurs == 0) {
3955 /* basically an elem* */
3956 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3957 ctxt->state);
3958 }
3959 }
3960 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3961 xmlAutomataStatePtr tmp;
3962 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003963
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003964 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3965 oldstate, NULL);
3966 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003967
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003968 counter = xmlAutomataNewCounter(ctxt->am,
3969 elem->minOccurs - 1,
3970 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003971
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003972 if (elem->refDecl != NULL) {
3973 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3974 elem->refDecl, ctxt,
3975 elem->refDecl->name);
3976 } else {
3977 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3978 ctxt->state,
3979 NULL,
3980 elem->name,
3981 type);
3982 }
3983 tmp = ctxt->state;
3984 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3985 counter);
3986 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3987 NULL,
3988 counter);
3989 if (elem->minOccurs == 0) {
3990 /* basically an elem? */
3991 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3992 ctxt->state);
3993 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003994
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003995 } else {
3996 if (elem->refDecl != NULL) {
3997 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3998 elem->refDecl, ctxt,
3999 elem->refDecl->name);
4000 } else {
4001 ctxt->state = xmlAutomataNewTransition(ctxt->am,
4002 ctxt->state,
4003 NULL,
4004 elem->name,
4005 type);
4006 }
4007 if (elem->minOccurs == 0) {
4008 /* basically an elem? */
4009 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4010 ctxt->state);
4011 }
4012 }
4013 break;
4014 }
4015 case XML_SCHEMA_TYPE_SEQUENCE:{
4016 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004017
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004018 /*
4019 * If max and min occurances are default (1) then
4020 * simply iterate over the subtypes
4021 */
4022 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4023 subtypes = type->subtypes;
4024 while (subtypes != NULL) {
4025 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4026 subtypes = subtypes->next;
4027 }
4028 } else {
4029 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004030
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004031 if (type->maxOccurs >= UNBOUNDED) {
4032 if (type->minOccurs > 1) {
4033 xmlAutomataStatePtr tmp;
4034 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004035
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004036 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4037 oldstate,
4038 NULL);
4039 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004040
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004041 counter = xmlAutomataNewCounter(ctxt->am,
4042 type->
4043 minOccurs - 1,
4044 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004045
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004046 subtypes = type->subtypes;
4047 while (subtypes != NULL) {
4048 xmlSchemaBuildAContentModel(subtypes, ctxt,
4049 name);
4050 subtypes = subtypes->next;
4051 }
4052 tmp = ctxt->state;
4053 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4054 oldstate, counter);
4055 ctxt->state =
4056 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4057 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004058
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004059 } else {
4060 subtypes = type->subtypes;
4061 while (subtypes != NULL) {
4062 xmlSchemaBuildAContentModel(subtypes, ctxt,
4063 name);
4064 subtypes = subtypes->next;
4065 }
4066 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4067 oldstate);
4068 if (type->minOccurs == 0) {
4069 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4070 ctxt->state);
4071 }
4072 }
4073 } else if ((type->maxOccurs > 1)
4074 || (type->minOccurs > 1)) {
4075 xmlAutomataStatePtr tmp;
4076 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004077
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004078 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4079 oldstate,
4080 NULL);
4081 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004082
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004083 counter = xmlAutomataNewCounter(ctxt->am,
4084 type->minOccurs -
4085 1,
4086 type->maxOccurs -
4087 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004088
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004089 subtypes = type->subtypes;
4090 while (subtypes != NULL) {
4091 xmlSchemaBuildAContentModel(subtypes, ctxt,
4092 name);
4093 subtypes = subtypes->next;
4094 }
4095 tmp = ctxt->state;
4096 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4097 counter);
4098 ctxt->state =
4099 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4100 counter);
4101 if (type->minOccurs == 0) {
4102 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4103 ctxt->state);
4104 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004105
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004106 } else {
4107 subtypes = type->subtypes;
4108 while (subtypes != NULL) {
4109 xmlSchemaBuildAContentModel(subtypes, ctxt,
4110 name);
4111 subtypes = subtypes->next;
4112 }
4113 if (type->minOccurs == 0) {
4114 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4115 ctxt->state);
4116 }
4117 }
4118 }
4119 break;
4120 }
4121 case XML_SCHEMA_TYPE_CHOICE:{
4122 xmlSchemaTypePtr subtypes;
4123 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004124
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004125 start = ctxt->state;
4126 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004127
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004128 /*
4129 * iterate over the subtypes and remerge the end with an
4130 * epsilon transition
4131 */
4132 if (type->maxOccurs == 1) {
4133 subtypes = type->subtypes;
4134 while (subtypes != NULL) {
4135 ctxt->state = start;
4136 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4137 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4138 subtypes = subtypes->next;
4139 }
4140 } else {
4141 int counter;
4142 xmlAutomataStatePtr hop;
4143 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4144 UNBOUNDED : type->maxOccurs - 1;
4145 int minOccurs =
4146 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004147
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004148 /*
4149 * use a counter to keep track of the number of transtions
4150 * which went through the choice.
4151 */
4152 counter =
4153 xmlAutomataNewCounter(ctxt->am, minOccurs,
4154 maxOccurs);
4155 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004156
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004157 subtypes = type->subtypes;
4158 while (subtypes != NULL) {
4159 ctxt->state = start;
4160 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4161 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4162 subtypes = subtypes->next;
4163 }
4164 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4165 counter);
4166 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4167 counter);
4168 }
4169 if (type->minOccurs == 0) {
4170 xmlAutomataNewEpsilon(ctxt->am, start, end);
4171 }
4172 ctxt->state = end;
4173 break;
4174 }
4175 case XML_SCHEMA_TYPE_ALL:{
4176 xmlAutomataStatePtr start;
4177 xmlSchemaTypePtr subtypes;
4178 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4179 int lax;
4180
4181 subtypes = type->subtypes;
4182 if (subtypes == NULL)
4183 break;
4184 start = ctxt->state;
4185 while (subtypes != NULL) {
4186 ctxt->state = start;
4187 elem = (xmlSchemaElementPtr) subtypes;
4188
4189 /* TODO : handle the namespace too */
4190 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4191 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4192 ctxt->state, elem->name, 1,
4193 1, subtypes);
4194 } else {
4195 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4196 ctxt->state, elem->name,
4197 elem->minOccurs,
4198 elem->maxOccurs,
4199 subtypes);
4200 }
4201 subtypes = subtypes->next;
4202 }
4203 lax = type->minOccurs == 0;
4204 ctxt->state =
4205 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4206 lax);
4207 break;
4208 }
4209 case XML_SCHEMA_TYPE_RESTRICTION:
4210 if (type->subtypes != NULL)
4211 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4212 break;
4213 case XML_SCHEMA_TYPE_EXTENSION:
4214 if (type->baseType != NULL) {
4215 xmlSchemaTypePtr subtypes;
4216
4217 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4218 subtypes = type->subtypes;
4219 while (subtypes != NULL) {
4220 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4221 subtypes = subtypes->next;
4222 }
4223 } else if (type->subtypes != NULL)
4224 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4225 break;
4226 case XML_SCHEMA_TYPE_GROUP:
4227 if (type->subtypes == NULL) {
4228 }
4229 case XML_SCHEMA_TYPE_COMPLEX:
4230 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4231 if (type->subtypes != NULL)
4232 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4233 break;
4234 default:
4235 xmlGenericError(xmlGenericErrorContext,
4236 "Found unexpected type %d in %s content model\n",
4237 type->type, name);
4238 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004239 }
4240}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004241
Daniel Veillard4255d502002-04-16 15:50:10 +00004242/**
4243 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004244 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004245 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004246 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004247 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004248 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004249 */
4250static void
4251xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004252 xmlSchemaParserCtxtPtr ctxt,
4253 const xmlChar * name)
4254{
Daniel Veillard4255d502002-04-16 15:50:10 +00004255 xmlAutomataStatePtr start;
4256
Daniel Veillard4255d502002-04-16 15:50:10 +00004257 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004258 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004259 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004260 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4261 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004262 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004265 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4266 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004267 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004268
4269#ifdef DEBUG_CONTENT
4270 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004271 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004272#endif
4273
Daniel Veillard4255d502002-04-16 15:50:10 +00004274 ctxt->am = xmlNewAutomata();
4275 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004276 xmlGenericError(xmlGenericErrorContext,
4277 "Cannot create automata for elem %s\n", name);
4278 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004279 }
4280 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4281 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4282 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004283 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004284 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004285 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4286 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004287 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004288 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4289 "Content model of %s is not determinist:\n", name,
4290 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004291 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004292#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004293 xmlGenericError(xmlGenericErrorContext,
4294 "Content model of %s:\n", name);
4295 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004296#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004297 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004298 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004299 xmlFreeAutomata(ctxt->am);
4300 ctxt->am = NULL;
4301}
4302
4303/**
4304 * xmlSchemaRefFixupCallback:
4305 * @elem: the schema element context
4306 * @ctxt: the schema parser context
4307 *
4308 * Free the resources associated to the schema parser context
4309 */
4310static void
4311xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 xmlSchemaParserCtxtPtr ctxt,
4313 const xmlChar * name,
4314 const xmlChar * context ATTRIBUTE_UNUSED,
4315 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004316{
4317 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004318 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004319 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004320 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004321
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004322 if (elem->subtypes != NULL) {
4323 xmlSchemaPErr(ctxt, elem->node,
4324 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4325 "Schemas: element %s have both ref and subtype\n",
4326 name, NULL);
4327 return;
4328 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004329 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004330
4331 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004332 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4333 "Schemas: element %s ref to %s not found\n",
4334 name, elem->ref);
4335 return;
4336 }
4337 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004339 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004340
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004341 if (elem->subtypes != NULL) {
4342 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4343 "Schemas: element %s have both type and subtype\n",
4344 name, NULL);
4345 return;
4346 }
4347 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4348 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004349
4350 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004351 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4352 "Schemas: element %s type %s not found\n", name,
4353 elem->namedType);
4354 return;
4355 }
4356 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004357 }
4358}
4359
4360/**
4361 * xmlSchemaTypeFixup:
4362 * @typeDecl: the schema type definition
4363 * @ctxt: the schema parser context
4364 *
4365 * Fixes the content model of the type.
4366 */
4367static void
4368xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004369 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004370{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004371 if (typeDecl == NULL)
4372 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004373 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004374 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004375 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004376 switch (typeDecl->type) {
4377 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4378 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4379 if (typeDecl->subtypes != NULL)
4380 typeDecl->contentType =
4381 typeDecl->subtypes->contentType;
4382 break;
4383 }
4384 case XML_SCHEMA_TYPE_RESTRICTION:{
4385 if (typeDecl->subtypes != NULL)
4386 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004387
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004388 if (typeDecl->base != NULL) {
4389 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004390
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004391 baseType =
4392 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4393 typeDecl->baseNs);
4394 if (baseType == NULL) {
4395 xmlSchemaPErr(ctxt, typeDecl->node,
4396 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 name, typeDecl->base);
4399 }
4400 typeDecl->baseType = baseType;
4401 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004402 if (typeDecl->subtypes == NULL)
4403 if (typeDecl->baseType != NULL)
4404 typeDecl->contentType =
4405 typeDecl->baseType->contentType;
4406 else
4407 /* 1.1.1 */
4408 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004409 else if ((typeDecl->subtypes->subtypes == NULL) &&
4410 ((typeDecl->subtypes->type ==
4411 XML_SCHEMA_TYPE_ALL)
4412 || (typeDecl->subtypes->type ==
4413 XML_SCHEMA_TYPE_SEQUENCE)))
4414 /* 1.1.2 */
4415 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4416 else if ((typeDecl->subtypes->type ==
4417 XML_SCHEMA_TYPE_CHOICE)
4418 && (typeDecl->subtypes->subtypes == NULL))
4419 /* 1.1.3 */
4420 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4421 else {
4422 /* 1.2 and 2.X are applied at the other layer */
4423 typeDecl->contentType =
4424 XML_SCHEMA_CONTENT_ELEMENTS;
4425 }
4426 break;
4427 }
4428 case XML_SCHEMA_TYPE_EXTENSION:{
4429 xmlSchemaContentType explicitContentType;
4430 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004431
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004432 if (typeDecl->base != NULL) {
4433 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004434
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004435 baseType =
4436 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4437 typeDecl->baseNs);
4438 if (baseType == NULL) {
4439 xmlSchemaPErr(ctxt, typeDecl->node,
4440 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004441 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004442 name, typeDecl->base);
4443 }
4444 typeDecl->baseType = baseType;
4445 }
4446 if (typeDecl->subtypes != NULL)
4447 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004448
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004449 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4450 if (typeDecl->subtypes == NULL)
4451 /* 1.1.1 */
4452 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4453 else if ((typeDecl->subtypes->subtypes == NULL) &&
4454 ((typeDecl->subtypes->type ==
4455 XML_SCHEMA_TYPE_ALL)
4456 || (typeDecl->subtypes->type ==
4457 XML_SCHEMA_TYPE_SEQUENCE)))
4458 /* 1.1.2 */
4459 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4460 else if ((typeDecl->subtypes->type ==
4461 XML_SCHEMA_TYPE_CHOICE)
4462 && (typeDecl->subtypes->subtypes == NULL))
4463 /* 1.1.3 */
4464 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004465
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004466 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4467 typeDecl->baseNs);
4468 if (base == NULL) {
4469 xmlSchemaPErr(ctxt, typeDecl->node,
4470 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4471 "Schemas: base type %s of type %s not found\n",
4472 typeDecl->base, name);
4473 return;
4474 }
4475 xmlSchemaTypeFixup(base, ctxt, NULL);
4476 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4477 /* 2.1 */
4478 typeDecl->contentType = base->contentType;
4479 } else if (base->contentType ==
4480 XML_SCHEMA_CONTENT_EMPTY) {
4481 /* 2.2 imbitable ! */
4482 typeDecl->contentType =
4483 XML_SCHEMA_CONTENT_ELEMENTS;
4484 } else {
4485 /* 2.3 imbitable pareil ! */
4486 typeDecl->contentType =
4487 XML_SCHEMA_CONTENT_ELEMENTS;
4488 }
4489 break;
4490 }
4491 case XML_SCHEMA_TYPE_COMPLEX:{
4492 if (typeDecl->subtypes == NULL) {
4493 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4494 } else {
4495 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4496 typeDecl->contentType =
4497 XML_SCHEMA_CONTENT_MIXED;
4498 else {
4499 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4500 NULL);
4501 if (typeDecl->subtypes != NULL)
4502 typeDecl->contentType =
4503 typeDecl->subtypes->contentType;
4504 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004505 if (typeDecl->attributes == NULL)
4506 typeDecl->attributes =
4507 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004508 }
4509 break;
4510 }
4511 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4512 if (typeDecl->subtypes == NULL) {
4513 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4514 } else {
4515 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4516 typeDecl->contentType =
4517 XML_SCHEMA_CONTENT_MIXED;
4518 else {
4519 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4520 NULL);
4521 if (typeDecl->subtypes != NULL)
4522 typeDecl->contentType =
4523 typeDecl->subtypes->contentType;
4524 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004525 if (typeDecl->attributes == NULL)
4526 typeDecl->attributes =
4527 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004528 }
4529 break;
4530 }
4531 case XML_SCHEMA_TYPE_SEQUENCE:
4532 case XML_SCHEMA_TYPE_GROUP:
4533 case XML_SCHEMA_TYPE_ALL:
4534 case XML_SCHEMA_TYPE_CHOICE:
4535 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4536 break;
4537 case XML_SCHEMA_TYPE_BASIC:
4538 case XML_SCHEMA_TYPE_ANY:
4539 case XML_SCHEMA_TYPE_FACET:
4540 case XML_SCHEMA_TYPE_SIMPLE:
4541 case XML_SCHEMA_TYPE_UR:
4542 case XML_SCHEMA_TYPE_ELEMENT:
4543 case XML_SCHEMA_TYPE_ATTRIBUTE:
4544 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4545 case XML_SCHEMA_TYPE_NOTATION:
4546 case XML_SCHEMA_TYPE_LIST:
4547 case XML_SCHEMA_TYPE_UNION:
4548 case XML_SCHEMA_FACET_MININCLUSIVE:
4549 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4550 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4551 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4552 case XML_SCHEMA_FACET_TOTALDIGITS:
4553 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4554 case XML_SCHEMA_FACET_PATTERN:
4555 case XML_SCHEMA_FACET_ENUMERATION:
4556 case XML_SCHEMA_FACET_WHITESPACE:
4557 case XML_SCHEMA_FACET_LENGTH:
4558 case XML_SCHEMA_FACET_MAXLENGTH:
4559 case XML_SCHEMA_FACET_MINLENGTH:
4560 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004561 if (typeDecl->subtypes != NULL)
4562 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004563 break;
4564 }
4565 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004566#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004567 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004568 xmlGenericError(xmlGenericErrorContext,
4569 "Type of %s : %s:%d :", name,
4570 typeDecl->node->doc->URL,
4571 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004572 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004574 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004575 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004576 case XML_SCHEMA_CONTENT_SIMPLE:
4577 xmlGenericError(xmlGenericErrorContext, "simple\n");
4578 break;
4579 case XML_SCHEMA_CONTENT_ELEMENTS:
4580 xmlGenericError(xmlGenericErrorContext, "elements\n");
4581 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004582 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4584 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004585 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004586 xmlGenericError(xmlGenericErrorContext, "empty\n");
4587 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004588 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004589 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4590 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004591 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004592 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4593 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004594 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004595 xmlGenericError(xmlGenericErrorContext, "basic\n");
4596 break;
4597 default:
4598 xmlGenericError(xmlGenericErrorContext,
4599 "not registered !!!\n");
4600 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004601 }
4602#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004603}
4604
4605/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004606 * xmlSchemaCheckFacet:
4607 * @facet: the facet
4608 * @typeDecl: the schema type definition
4609 * @ctxt: the schema parser context or NULL
4610 * @name: name of the type
4611 *
4612 * Checks the default values types, especially for facets
4613 *
4614 * Returns 0 if okay or -1 in cae of error
4615 */
4616int
4617xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004618 xmlSchemaTypePtr typeDecl,
4619 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004620{
4621 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4622 int ret = 0;
4623
4624 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004625 nonNegativeIntegerType =
4626 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4627 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004628 }
4629 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004630 case XML_SCHEMA_FACET_MININCLUSIVE:
4631 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4632 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4633 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4634 /*
4635 * Okay we need to validate the value
4636 * at that point.
4637 */
4638 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004639
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004640 vctxt = xmlSchemaNewValidCtxt(NULL);
4641 if (vctxt == NULL)
4642 break;
4643 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4644 facet->value);
4645 facet->val = vctxt->value;
4646 vctxt->value = NULL;
4647 if (facet->val == NULL) {
4648 /* error code */
4649 if (ctxt != NULL) {
4650 xmlSchemaPErr(ctxt, facet->node,
4651 XML_SCHEMAP_INVALID_FACET,
4652 "Schemas: type %s facet value %s invalid\n",
4653 name, facet->value);
4654 }
4655 ret = -1;
4656 }
4657 xmlSchemaFreeValidCtxt(vctxt);
4658 break;
4659 }
4660 case XML_SCHEMA_FACET_ENUMERATION:{
4661 /*
4662 * Okay we need to validate the value
4663 * at that point.
4664 */
4665 xmlSchemaValidCtxtPtr vctxt;
4666 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004667
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004668 vctxt = xmlSchemaNewValidCtxt(NULL);
4669 if (vctxt == NULL)
4670 break;
4671 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4672 facet->value);
4673 if (tmp != 0) {
4674 if (ctxt != NULL) {
4675 xmlSchemaPErr(ctxt, facet->node,
4676 XML_SCHEMAP_INVALID_ENUM,
4677 "Schemas: type %s enumeration value %s invalid\n",
4678 name, facet->value);
4679 }
4680 ret = -1;
4681 }
4682 xmlSchemaFreeValidCtxt(vctxt);
4683 break;
4684 }
4685 case XML_SCHEMA_FACET_PATTERN:
4686 facet->regexp = xmlRegexpCompile(facet->value);
4687 if (facet->regexp == NULL) {
4688 xmlSchemaPErr(ctxt, typeDecl->node,
4689 XML_SCHEMAP_REGEXP_INVALID,
4690 "Schemas: type %s facet regexp %s invalid\n",
4691 name, facet->value);
4692 ret = -1;
4693 }
4694 break;
4695 case XML_SCHEMA_FACET_TOTALDIGITS:
4696 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4697 case XML_SCHEMA_FACET_LENGTH:
4698 case XML_SCHEMA_FACET_MAXLENGTH:
4699 case XML_SCHEMA_FACET_MINLENGTH:{
4700 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004701
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004702 tmp =
4703 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4704 facet->value,
4705 &facet->val);
4706 if (tmp != 0) {
4707 /* error code */
4708 if (ctxt != NULL) {
4709 xmlSchemaPErr(ctxt, facet->node,
4710 XML_SCHEMAP_INVALID_FACET_VALUE,
4711 "Schemas: type %s facet value %s invalid\n",
4712 name, facet->value);
4713 }
4714 ret = -1;
4715 }
4716 break;
4717 }
4718 case XML_SCHEMA_FACET_WHITESPACE:{
4719 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4720 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4721 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4722 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4723 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4724 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4725 } else {
4726 if (ctxt != NULL) {
4727 xmlSchemaPErr(ctxt, facet->node,
4728 XML_SCHEMAP_INVALID_WHITE_SPACE,
4729 "Schemas: type %s whiteSpace value %s invalid\n",
4730 name, facet->value);
4731 }
4732 ret = -1;
4733 }
4734 }
4735 default:
4736 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004737 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004738 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004739}
4740
4741/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004742 * xmlSchemaCheckDefaults:
4743 * @typeDecl: the schema type definition
4744 * @ctxt: the schema parser context
4745 *
4746 * Checks the default values types, especially for facets
4747 */
4748static void
4749xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004750 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004751{
Daniel Veillard4255d502002-04-16 15:50:10 +00004752 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004753 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004754 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004755 if (typeDecl->facets != NULL) {
4756 xmlSchemaFacetPtr facet = typeDecl->facets;
4757
4758 while (facet != NULL) {
4759 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4760 facet = facet->next;
4761 }
4762 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004763 }
4764}
4765
4766/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004767 * xmlSchemaAttrGrpFixup:
4768 * @attrgrpDecl: the schema attribute definition
4769 * @ctxt: the schema parser context
4770 * @name: the attribute name
4771 *
4772 * Fixes finish doing the computations on the attributes definitions
4773 */
4774static void
4775xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004776 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004777{
4778 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004780 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004781 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004782 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004783 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004784
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004785 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4786 attrgrpDecl->refNs);
4787 if (ref == NULL) {
4788 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4789 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4790 "Schemas: attribute group %s reference %s not found\n",
4791 name, attrgrpDecl->ref);
4792 return;
4793 }
4794 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4795 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004796 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004797 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4798 "Schemas: attribute %s has no attributes nor reference\n",
4799 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004800 }
4801}
4802
4803/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 * xmlSchemaAttrFixup:
4805 * @attrDecl: the schema attribute definition
4806 * @ctxt: the schema parser context
4807 * @name: the attribute name
4808 *
4809 * Fixes finish doing the computations on the attributes definitions
4810 */
4811static void
4812xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004813 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004814{
4815 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004816 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004817 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004818 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004819 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004821
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004822 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4823 attrDecl->typeNs);
4824 if (type == NULL) {
4825 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4826 "Schemas: attribute %s type %s not found\n",
4827 name, attrDecl->typeName);
4828 }
4829 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004830 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004832
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004833 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4834 attrDecl->refNs);
4835 if (ref == NULL) {
4836 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4837 "Schemas: attribute %s reference %s not found\n",
4838 name, attrDecl->ref);
4839 return;
4840 }
4841 xmlSchemaAttrFixup(ref, ctxt, NULL);
4842 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004843 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004844 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4845 "Schemas: attribute %s has no type nor reference\n",
4846 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004847 }
4848}
4849
4850/**
4851 * xmlSchemaParse:
4852 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004853 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004854 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 * XML Shema struture which can be used to validate instances.
4856 * *WARNING* this interface is highly subject to change
4857 *
4858 * Returns the internal XML Schema structure built from the resource or
4859 * NULL in case of error
4860 */
4861xmlSchemaPtr
4862xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4863{
4864 xmlSchemaPtr ret = NULL;
4865 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004866 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004867 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004868 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004869
4870 xmlSchemaInitTypes();
4871
Daniel Veillard6045c902002-10-09 21:13:59 +00004872 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004873 return (NULL);
4874
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004875 nberrors = ctxt->nberrors;
4876 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004877 ctxt->counter = 0;
4878 ctxt->container = NULL;
4879
4880 /*
4881 * First step is to parse the input document into an DOM/Infoset
4882 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004883 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004884 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4885 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004886 if (doc == NULL) {
4887 xmlSchemaPErr(ctxt, NULL,
4888 XML_SCHEMAP_FAILED_LOAD,
4889 "xmlSchemaParse: could not load %s\n",
4890 ctxt->URL, NULL);
4891 return (NULL);
4892 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004893 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004894 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4895 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004896 if (doc == NULL) {
4897 xmlSchemaPErr(ctxt, NULL,
4898 XML_SCHEMAP_FAILED_PARSE,
4899 "xmlSchemaParse: could not parse\n",
4900 NULL, NULL);
4901 return (NULL);
4902 }
4903 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00004904 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00004905 } else if (ctxt->doc != NULL) {
4906 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004907 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00004908 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004909 xmlSchemaPErr(ctxt, NULL,
4910 XML_SCHEMAP_NOTHING_TO_PARSE,
4911 "xmlSchemaParse: could not parse\n",
4912 NULL, NULL);
4913 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004914 }
4915
4916 /*
4917 * Then extract the root and Schema parse it
4918 */
4919 root = xmlDocGetRootElement(doc);
4920 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004921 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4922 XML_SCHEMAP_NOROOT,
4923 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00004924 if (!preserve) {
4925 xmlFreeDoc(doc);
4926 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004927 return (NULL);
4928 }
4929
4930 /*
4931 * Remove all the blank text nodes
4932 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004933 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00004934
4935 /*
4936 * Then do the parsing for good
4937 */
4938 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004939 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00004940 if (!preserve) {
4941 xmlFreeDoc(doc);
4942 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004943 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004944 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004945 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00004946 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00004947
4948 /*
4949 * Then fix all the references.
4950 */
4951 ctxt->schema = ret;
4952 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004953 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004954
4955 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00004956 * Then fixup all attributes declarations
4957 */
4958 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4959
4960 /*
4961 * Then fixup all attributes group declarations
4962 */
4963 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4964 ctxt);
4965
4966 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00004967 * Then fixup all types properties
4968 */
4969 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4970
4971 /*
4972 * Then build the content model for all elements
4973 */
4974 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004975 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004976
4977 /*
4978 * Then check the defaults part of the type like facets values
4979 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004980 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4981 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004982
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004983 if (ctxt->nberrors != 0) {
4984 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004985 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004986 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004987 return (ret);
4988}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004989
Daniel Veillard4255d502002-04-16 15:50:10 +00004990/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004991 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004992 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004993 * @err: the error callback
4994 * @warn: the warning callback
4995 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004996 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004997 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004998 */
4999void
5000xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005001 xmlSchemaValidityErrorFunc err,
5002 xmlSchemaValidityWarningFunc warn, void *ctx)
5003{
Daniel Veillard4255d502002-04-16 15:50:10 +00005004 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005005 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005006 ctxt->error = err;
5007 ctxt->warning = warn;
5008 ctxt->userData = ctx;
5009}
5010
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005011/**
5012 * xmlSchemaFacetTypeToString:
5013 * @type: the facet type
5014 *
5015 * Convert the xmlSchemaTypeType to a char string.
5016 *
5017 * Returns the char string representation of the facet type if the
5018 * type is a facet and an "Internal Error" string otherwise.
5019 */
5020static const char *
5021xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5022{
5023 switch (type) {
5024 case XML_SCHEMA_FACET_PATTERN:
5025 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005026 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005027 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005028 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005029 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005030 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005031 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005032 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005033 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005034 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005035 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005036 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005037 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005038 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005039 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005040 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005041 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005042 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005043 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005044 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005045 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005046 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005047 return ("fractionDigits");
5048 default:
5049 break;
5050 }
5051 return ("Internal Error");
5052}
5053
5054/**
5055 * xmlSchemaValidateFacets:
5056 * @ctxt: a schema validation context
5057 * @base: the base type
5058 * @facets: the list of facets to check
5059 * @value: the lexical repr of the value to validate
5060 * @val: the precomputed value
5061 *
5062 * Check a value against all facet conditions
5063 *
5064 * Returns 0 if the element is schemas valid, a positive error code
5065 * number otherwise and -1 in case of internal or API error.
5066 */
5067static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005068xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5069 xmlSchemaTypePtr base,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005070 xmlSchemaFacetPtr facets, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005071{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005072 int ret = 0;
5073 int tmp = 0;
5074 xmlSchemaTypeType type;
5075 xmlSchemaFacetPtr facet = facets;
5076
5077 while (facet != NULL) {
5078 type = facet->type;
5079 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005080 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005081
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082 while (facet != NULL) {
5083 tmp =
5084 xmlSchemaValidateFacet(base, facet, value,
5085 ctxt->value);
5086 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005087 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005088 }
5089 facet = facet->next;
5090 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005091 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005092 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005093
5094 if (tmp != 0) {
5095 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005096 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 +00005097 }
5098 if (facet != NULL)
5099 facet = facet->next;
5100 }
5101 return (ret);
5102}
5103
Daniel Veillard4255d502002-04-16 15:50:10 +00005104/************************************************************************
5105 * *
5106 * Simple type validation *
5107 * *
5108 ************************************************************************/
5109
5110/**
5111 * xmlSchemaValidateSimpleValue:
5112 * @ctxt: a schema validation context
5113 * @type: the type declaration
5114 * @value: the value to validate
5115 *
5116 * Validate a value against a simple type
5117 *
5118 * Returns 0 if the value is valid, a positive error code
5119 * number otherwise and -1 in case of internal or API error.
5120 */
5121static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005122xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005123 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005124{
Daniel Veillard4255d502002-04-16 15:50:10 +00005125 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005126
Daniel Veillard4255d502002-04-16 15:50:10 +00005127 /*
5128 * First normalize the value accordingly to Schema Datatype
5129 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5130 */
5131 /*
5132 * Then check the normalized value against the lexical space of the
5133 * type.
5134 */
5135 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005136 if (ctxt->value != NULL) {
5137 xmlSchemaFreeValue(ctxt->value);
5138 ctxt->value = NULL;
5139 }
5140 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5141 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005142 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005143 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 +00005144 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005145 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005146 xmlSchemaTypePtr base;
5147 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005148
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005149 base = type->baseType;
5150 if (base != NULL) {
5151 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5152 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005153 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005154 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005155
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005156 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005157 * Do not validate facets or attributes when working on
5158 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005159 */
5160 if (ctxt->schema != NULL) {
5161 if (ret == 0) {
5162 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005163 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005164 }
5165 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005166 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005168
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005169 base = type->subtypes;
5170 if (base != NULL) {
5171 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5172 } else {
5173 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005174 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005176 const xmlChar *cur, *end;
5177 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005178 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005179
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005180 base = type->subtypes;
5181 if (base == NULL) {
5182 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5183 "Internal: List type %s has no base type\n",
5184 type->name, NULL);
5185 return (-1);
5186 }
5187 cur = value;
5188 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005189 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005190 cur++;
5191 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005192 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005193 end++;
5194 if (end == cur)
5195 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005196 tmp = xmlStrndup(cur, end - cur);
5197 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
5198 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005199 if (ret2 != 0)
5200 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005201 cur = end;
5202 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005203 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005204 TODO
5205 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005206 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005207}
5208
5209/************************************************************************
5210 * *
5211 * DOM Validation code *
5212 * *
5213 ************************************************************************/
5214
5215static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005216 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005217static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005218 xmlNodePtr elem,
5219 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005220static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005221 xmlNodePtr elem,
5222 xmlSchemaElementPtr elemDecl,
5223 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005224
5225/**
5226 * xmlSchemaRegisterAttributes:
5227 * @ctxt: a schema validation context
5228 * @attrs: a list of attributes
5229 *
5230 * Register the list of attributes as the set to be validated on that element
5231 *
5232 * Returns -1 in case of error, 0 otherwise
5233 */
5234static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005235xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5236{
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005238 if ((attrs->ns != NULL) &&
5239 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5240 attrs = attrs->next;
5241 continue;
5242 }
5243 if (ctxt->attrNr >= ctxt->attrMax) {
5244 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005245
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005246 ctxt->attrMax *= 2;
5247 tmp = (xmlSchemaAttrStatePtr)
5248 xmlRealloc(ctxt->attr, ctxt->attrMax *
5249 sizeof(xmlSchemaAttrState));
5250 if (tmp == NULL) {
5251 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5252 ctxt->attrMax /= 2;
5253 return (-1);
5254 }
5255 ctxt->attr = tmp;
5256 }
5257 ctxt->attr[ctxt->attrNr].attr = attrs;
5258 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5259 ctxt->attrNr++;
5260 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005261 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005262 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005263}
5264
5265/**
5266 * xmlSchemaCheckAttributes:
5267 * @ctxt: a schema validation context
5268 * @node: the node carrying it.
5269 *
5270 * Check that the registered set of attributes on the current node
5271 * has been properly validated.
5272 *
5273 * Returns 0 if validity constraints are met, 1 otherwise.
5274 */
5275static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005276xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5277{
Daniel Veillard4255d502002-04-16 15:50:10 +00005278 int ret = 0;
5279 int i;
5280
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005281 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5282 if (ctxt->attr[i].attr == NULL)
5283 break;
5284 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5285 ret = 1;
5286 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5287 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005288 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005289 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005290}
5291
5292/**
5293 * xmlSchemaValidateSimpleContent:
5294 * @ctxt: a schema validation context
5295 * @elem: an element
5296 * @type: the type declaration
5297 *
5298 * Validate the content of an element expected to be a simple type
5299 *
5300 * Returns 0 if the element is schemas valid, a positive error code
5301 * number otherwise and -1 in case of internal or API error.
5302 */
5303static int
5304xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005305 xmlNodePtr node ATTRIBUTE_UNUSED)
5306{
Daniel Veillard4255d502002-04-16 15:50:10 +00005307 xmlNodePtr child;
5308 xmlSchemaTypePtr type, base;
5309 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005310 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005311
5312 child = ctxt->node;
5313 type = ctxt->type;
5314
5315 /*
5316 * Validation Rule: Element Locally Valid (Type): 3.1.3
5317 */
5318 value = xmlNodeGetContent(child);
5319 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5320 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005321 case XML_SCHEMA_TYPE_RESTRICTION:{
5322 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005323
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005324 base = type->baseType;
5325 if (base != NULL) {
5326 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5327 } else {
5328 TODO}
5329 if (ret == 0) {
5330 facet = type->facets;
5331 ret =
5332 xmlSchemaValidateFacets(ctxt, base, facet, value);
5333 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005334 if ((ret == 0) && (type->attributes != NULL)) {
5335 ret = xmlSchemaValidateAttributes(ctxt, node,
5336 type->attributes);
5337 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005338 break;
5339 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005340 case XML_SCHEMA_TYPE_EXTENSION:{
5341 TODO
5342 break;
5343 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005345 TODO
5346 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005347 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005348 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005349
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005351}
5352
5353/**
5354 * xmlSchemaValidateCheckNodeList
5355 * @nodelist: the list of nodes
5356 *
5357 * Check the node list is only made of text nodes and entities pointing
5358 * to text nodes
5359 *
5360 * Returns 1 if true, 0 if false and -1 in case of error
5361 */
5362static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005363xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5364{
Daniel Veillard4255d502002-04-16 15:50:10 +00005365 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005366 if (nodelist->type == XML_ENTITY_REF_NODE) {
5367 TODO /* implement recursion in the entity content */
5368 }
5369 if ((nodelist->type != XML_TEXT_NODE) &&
5370 (nodelist->type != XML_COMMENT_NODE) &&
5371 (nodelist->type != XML_PI_NODE) &&
5372 (nodelist->type != XML_PI_NODE)) {
5373 return (0);
5374 }
5375 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005376 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005377 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005378}
5379
5380/**
5381 * xmlSchemaSkipIgnored:
5382 * @ctxt: a schema validation context
5383 * @type: the current type context
5384 * @node: the top node.
5385 *
5386 * Skip ignorable nodes in that context
5387 *
5388 * Returns the new sibling
5389 * number otherwise and -1 in case of internal or API error.
5390 */
5391static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005392xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005393 xmlSchemaTypePtr type, xmlNodePtr node)
5394{
Daniel Veillard4255d502002-04-16 15:50:10 +00005395 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005396
Daniel Veillard4255d502002-04-16 15:50:10 +00005397 /*
5398 * TODO complete and handle entities
5399 */
5400 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005401 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005402 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005403 ((node->type == XML_COMMENT_NODE) ||
5404 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5405 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5406 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5407 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005408 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005409 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005410}
5411
5412/**
5413 * xmlSchemaValidateCallback:
5414 * @ctxt: a schema validation context
5415 * @name: the name of the element detected (might be NULL)
5416 * @type: the type
5417 *
5418 * A transition has been made in the automata associated to an element
5419 * content model
5420 */
5421static void
5422xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005423 const xmlChar * name ATTRIBUTE_UNUSED,
5424 xmlSchemaTypePtr type, xmlNodePtr node)
5425{
Daniel Veillard4255d502002-04-16 15:50:10 +00005426 xmlSchemaTypePtr oldtype = ctxt->type;
5427 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005428
Daniel Veillard4255d502002-04-16 15:50:10 +00005429#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005430 xmlGenericError(xmlGenericErrorContext,
5431 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005432 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005433#endif
5434 ctxt->type = type;
5435 ctxt->node = node;
5436 xmlSchemaValidateContent(ctxt, node);
5437 ctxt->type = oldtype;
5438 ctxt->node = oldnode;
5439}
5440
5441
5442#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005443
Daniel Veillard4255d502002-04-16 15:50:10 +00005444/**
5445 * xmlSchemaValidateSimpleRestrictionType:
5446 * @ctxt: a schema validation context
5447 * @node: the top node.
5448 *
5449 * Validate the content of a restriction type.
5450 *
5451 * Returns 0 if the element is schemas valid, a positive error code
5452 * number otherwise and -1 in case of internal or API error.
5453 */
5454static int
5455xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5456 xmlNodePtr node)
5457{
5458 xmlNodePtr child;
5459 xmlSchemaTypePtr type;
5460 int ret;
5461
5462 child = ctxt->node;
5463 type = ctxt->type;
5464
5465 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005466 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005467 return (-1);
5468 }
5469 /*
5470 * Only text and text based entities references shall be found there
5471 */
5472 ret = xmlSchemaValidateCheckNodeList(child);
5473 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005474 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005475 return (-1);
5476 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005477 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 +00005478 return (-1);
5479 }
5480 ctxt->type = type->subtypes;
5481 xmlSchemaValidateContent(ctxt, node);
5482 ctxt->type = type;
5483 return (ret);
5484}
5485#endif
5486
5487/**
5488 * xmlSchemaValidateSimpleType:
5489 * @ctxt: a schema validation context
5490 * @node: the top node.
5491 *
5492 * Validate the content of an simple type.
5493 *
5494 * Returns 0 if the element is schemas valid, a positive error code
5495 * number otherwise and -1 in case of internal or API error.
5496 */
5497static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005498xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5499{
Daniel Veillard4255d502002-04-16 15:50:10 +00005500 xmlNodePtr child;
5501 xmlSchemaTypePtr type;
5502 xmlAttrPtr attr;
5503 int ret;
5504
5505 child = ctxt->node;
5506 type = ctxt->type;
5507
5508 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005509 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5510 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005511 }
5512 /*
5513 * Only text and text based entities references shall be found there
5514 */
5515 ret = xmlSchemaValidateCheckNodeList(child);
5516 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005517 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5518 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005519 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005520 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5521 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005522 }
5523 /*
5524 * Validation Rule: Element Locally Valid (Type): 3.1.1
5525 */
5526 attr = node->properties;
5527 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005528 if ((attr->ns == NULL) ||
5529 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5530 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5531 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5532 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5533 (!xmlStrEqual
5534 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5535 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5536 return (ctxt->err);
5537 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005538 }
5539
5540 ctxt->type = type->subtypes;
5541 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5542 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005543 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005544}
5545
5546/**
5547 * xmlSchemaValidateElementType:
5548 * @ctxt: a schema validation context
5549 * @node: the top node.
5550 *
5551 * Validate the content of an element type.
5552 * Validation Rule: Element Locally Valid (Complex Type)
5553 *
5554 * Returns 0 if the element is schemas valid, a positive error code
5555 * number otherwise and -1 in case of internal or API error.
5556 */
5557static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005558xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5559{
Daniel Veillard4255d502002-04-16 15:50:10 +00005560 xmlNodePtr child;
5561 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005562 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005563 xmlSchemaElementPtr decl;
5564 int ret, attrBase;
5565
5566 oldregexp = ctxt->regexp;
5567
5568 child = ctxt->node;
5569 type = ctxt->type;
5570
5571 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005572 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5573 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005574 }
5575 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005576 if (type->minOccurs > 0) {
5577 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5578 }
5579 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005580 }
5581
5582 /*
5583 * Verify the element matches
5584 */
5585 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005586 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5587 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005588 }
5589 /*
5590 * Verify the attributes
5591 */
5592 attrBase = ctxt->attrBase;
5593 ctxt->attrBase = ctxt->attrNr;
5594 xmlSchemaRegisterAttributes(ctxt, child->properties);
5595 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5596 /*
5597 * Verify the element content recursively
5598 */
5599 decl = (xmlSchemaElementPtr) type;
5600 oldregexp = ctxt->regexp;
5601 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005602 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5603 (xmlRegExecCallbacks)
5604 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005605#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005606 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005607#endif
5608 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005609 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5610 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005611
5612 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005613 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005614#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005615 xmlGenericError(xmlGenericErrorContext,
5616 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005617#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005618 if (ret == 0) {
5619 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5620 } else if (ret < 0) {
5621 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005622#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005623 } else {
5624 xmlGenericError(xmlGenericErrorContext,
5625 "Element %s content check succeeded\n",
5626 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005627
5628#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005629 }
5630 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005631 }
5632 /*
5633 * Verify that all attributes were Schemas-validated
5634 */
5635 xmlSchemaCheckAttributes(ctxt, node);
5636 ctxt->attrNr = ctxt->attrBase;
5637 ctxt->attrBase = attrBase;
5638
5639 ctxt->regexp = oldregexp;
5640
5641 ctxt->node = child;
5642 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005643 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005644}
5645
5646/**
5647 * xmlSchemaValidateBasicType:
5648 * @ctxt: a schema validation context
5649 * @node: the top node.
5650 *
5651 * Validate the content of an element expected to be a basic type type
5652 *
5653 * Returns 0 if the element is schemas valid, a positive error code
5654 * number otherwise and -1 in case of internal or API error.
5655 */
5656static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005657xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5658{
Daniel Veillard4255d502002-04-16 15:50:10 +00005659 int ret;
5660 xmlNodePtr child, cur;
5661 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005662 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005663
5664 child = ctxt->node;
5665 type = ctxt->type;
5666
5667 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005668 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5669 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005670 }
5671 /*
5672 * First check the content model of the node.
5673 */
5674 cur = child;
5675 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005676 switch (cur->type) {
5677 case XML_TEXT_NODE:
5678 case XML_CDATA_SECTION_NODE:
5679 case XML_PI_NODE:
5680 case XML_COMMENT_NODE:
5681 case XML_XINCLUDE_START:
5682 case XML_XINCLUDE_END:
5683 break;
5684 case XML_ENTITY_REF_NODE:
5685 case XML_ENTITY_NODE:
5686 TODO break;
5687 case XML_ELEMENT_NODE:
5688 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5689 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 case XML_ATTRIBUTE_NODE:
5691 case XML_DOCUMENT_NODE:
5692 case XML_DOCUMENT_TYPE_NODE:
5693 case XML_DOCUMENT_FRAG_NODE:
5694 case XML_NOTATION_NODE:
5695 case XML_HTML_DOCUMENT_NODE:
5696 case XML_DTD_NODE:
5697 case XML_ELEMENT_DECL:
5698 case XML_ATTRIBUTE_DECL:
5699 case XML_ENTITY_DECL:
5700 case XML_NAMESPACE_DECL:
5701#ifdef LIBXML_DOCB_ENABLED
5702 case XML_DOCB_DOCUMENT_NODE:
5703#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005704 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5705 return (ctxt->err);
5706 }
5707 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005708 }
5709 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005710 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005711 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005712 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005713
5714 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005715 xmlSchemaFreeValue(ctxt->value);
5716 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005717 }
5718 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5719 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005720 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005721 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005722 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 +00005723 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005724 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005725}
5726
5727/**
5728 * xmlSchemaValidateComplexType:
5729 * @ctxt: a schema validation context
5730 * @node: the top node.
5731 *
5732 * Validate the content of an element expected to be a complex type type
5733 * xmlschema-1.html#cvc-complex-type
5734 * Validation Rule: Element Locally Valid (Complex Type)
5735 *
5736 * Returns 0 if the element is schemas valid, a positive error code
5737 * number otherwise and -1 in case of internal or API error.
5738 */
5739static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005740xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5741{
Daniel Veillard4255d502002-04-16 15:50:10 +00005742 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005743 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005744 int ret;
5745
5746 child = ctxt->node;
5747 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005748 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005749
Daniel Veillard4255d502002-04-16 15:50:10 +00005750 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005751 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005752 if (type->baseType != NULL) {
5753 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005754 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5755 }
5756 if (type->attributes != NULL) {
5757 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5758 }
5759 subtype = type->subtypes;
5760 while (subtype != NULL) {
5761 ctxt->type = subtype;
5762 xmlSchemaValidateComplexType(ctxt, node);
5763 subtype = subtype->next;
5764 }
5765 break;
5766 case XML_SCHEMA_CONTENT_ELEMENTS:
5767 case XML_SCHEMA_CONTENT_MIXED:
5768 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5769 /*
5770 * Skip ignorable nodes in that context
5771 */
5772 child = xmlSchemaSkipIgnored(ctxt, type, child);
5773 while (child != NULL) {
5774 if (child->type == XML_ELEMENT_NODE) {
5775 ret = xmlRegExecPushString(ctxt->regexp,
5776 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005777#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005778 if (ret < 0)
5779 xmlGenericError(xmlGenericErrorContext,
5780 " --> %s Error\n", child->name);
5781 else
5782 xmlGenericError(xmlGenericErrorContext,
5783 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005784#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005785 }
5786 child = child->next;
5787 /*
5788 * Skip ignorable nodes in that context
5789 */
5790 child = xmlSchemaSkipIgnored(ctxt, type, child);
5791 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005792 if (type->attributes != NULL) {
5793 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5794 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005795 break;
5796 case XML_SCHEMA_CONTENT_BASIC:{
5797 if (type->subtypes != NULL) {
5798 ctxt->type = type->subtypes;
5799 xmlSchemaValidateComplexType(ctxt, node);
5800 }
5801 if (type->baseType != NULL) {
5802 ctxt->type = type->baseType;
5803 xmlSchemaValidateBasicType(ctxt, node);
5804 }
5805 if (type->attributes != NULL) {
5806 xmlSchemaValidateAttributes(ctxt, node,
5807 type->attributes);
5808 }
5809 ctxt->type = type;
5810 break;
5811 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005812 case XML_SCHEMA_CONTENT_SIMPLE:{
5813 if (type->subtypes != NULL) {
5814 ctxt->type = type->subtypes;
5815 xmlSchemaValidateComplexType(ctxt, node);
5816 }
5817 if (type->baseType != NULL) {
5818 ctxt->type = type->baseType;
5819 xmlSchemaValidateComplexType(ctxt, node);
5820 }
5821 if (type->attributes != NULL) {
5822 xmlSchemaValidateAttributes(ctxt, node,
5823 type->attributes);
5824 }
5825 ctxt->type = type;
5826 break;
5827 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 default:
5829 TODO xmlGenericError(xmlGenericErrorContext,
5830 "unimplemented content type %d\n",
5831 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005832 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005833 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005834}
5835
5836/**
5837 * xmlSchemaValidateContent:
5838 * @ctxt: a schema validation context
5839 * @elem: an element
5840 * @type: the type declaration
5841 *
5842 * Validate the content of an element against the type.
5843 *
5844 * Returns 0 if the element is schemas valid, a positive error code
5845 * number otherwise and -1 in case of internal or API error.
5846 */
5847static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005848xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5849{
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 xmlNodePtr child;
5851 xmlSchemaTypePtr type;
5852
5853 child = ctxt->node;
5854 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005855 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005856
Daniel Veillarde19fc232002-04-22 16:01:24 +00005857 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005858 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005859
Daniel Veillard4255d502002-04-16 15:50:10 +00005860 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005861 case XML_SCHEMA_TYPE_ANY:
5862 /* Any type will do it, fine */
5863 TODO /* handle recursivity */
5864 break;
5865 case XML_SCHEMA_TYPE_COMPLEX:
5866 xmlSchemaValidateComplexType(ctxt, node);
5867 break;
5868 case XML_SCHEMA_TYPE_ELEMENT:{
5869 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5870
5871 /*
5872 * Handle element reference here
5873 */
5874 if (decl->ref != NULL) {
5875 if (decl->refDecl == NULL) {
5876 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5877 return (-1);
5878 }
5879 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5880 decl = decl->refDecl;
5881 }
5882 xmlSchemaValidateElementType(ctxt, node);
5883 ctxt->type = type;
5884 break;
5885 }
5886 case XML_SCHEMA_TYPE_BASIC:
5887 xmlSchemaValidateBasicType(ctxt, node);
5888 break;
5889 case XML_SCHEMA_TYPE_FACET:
5890 TODO break;
5891 case XML_SCHEMA_TYPE_SIMPLE:
5892 xmlSchemaValidateSimpleType(ctxt, node);
5893 break;
5894 case XML_SCHEMA_TYPE_SEQUENCE:
5895 TODO break;
5896 case XML_SCHEMA_TYPE_CHOICE:
5897 TODO break;
5898 case XML_SCHEMA_TYPE_ALL:
5899 TODO break;
5900 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5901 TODO break;
5902 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5903 TODO break;
5904 case XML_SCHEMA_TYPE_UR:
5905 TODO break;
5906 case XML_SCHEMA_TYPE_RESTRICTION:
5907 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5908 TODO break;
5909 case XML_SCHEMA_TYPE_EXTENSION:
5910 TODO break;
5911 case XML_SCHEMA_TYPE_ATTRIBUTE:
5912 TODO break;
5913 case XML_SCHEMA_TYPE_GROUP:
5914 TODO break;
5915 case XML_SCHEMA_TYPE_NOTATION:
5916 TODO break;
5917 case XML_SCHEMA_TYPE_LIST:
5918 TODO break;
5919 case XML_SCHEMA_TYPE_UNION:
5920 TODO break;
5921 case XML_SCHEMA_FACET_MININCLUSIVE:
5922 TODO break;
5923 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5924 TODO break;
5925 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5926 TODO break;
5927 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5928 TODO break;
5929 case XML_SCHEMA_FACET_TOTALDIGITS:
5930 TODO break;
5931 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5932 TODO break;
5933 case XML_SCHEMA_FACET_PATTERN:
5934 TODO break;
5935 case XML_SCHEMA_FACET_ENUMERATION:
5936 TODO break;
5937 case XML_SCHEMA_FACET_WHITESPACE:
5938 TODO break;
5939 case XML_SCHEMA_FACET_LENGTH:
5940 TODO break;
5941 case XML_SCHEMA_FACET_MAXLENGTH:
5942 TODO break;
5943 case XML_SCHEMA_FACET_MINLENGTH:
5944 TODO break;
5945 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5946 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005947 }
5948 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5949
5950 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005951 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005952 ctxt->node = ctxt->node->next;
5953 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005954 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005955}
5956
5957/**
5958 * xmlSchemaValidateType:
5959 * @ctxt: a schema validation context
5960 * @elem: an element
5961 * @type: the list of type declarations
5962 *
5963 * Validate the content of an element against the types.
5964 *
5965 * Returns 0 if the element is schemas valid, a positive error code
5966 * number otherwise and -1 in case of internal or API error.
5967 */
5968static int
5969xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005970 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5971{
Daniel Veillard4255d502002-04-16 15:50:10 +00005972 xmlChar *nil;
5973
Daniel Veillard2db8c122003-07-08 12:16:59 +00005974 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005975 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005976
Daniel Veillard4255d502002-04-16 15:50:10 +00005977 /*
5978 * 3.3.4 : 2
5979 */
5980 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005981 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5982 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005983 }
5984 /*
5985 * 3.3.4: 3
5986 */
5987 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5988 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005989 /* 3.3.4: 3.2 */
5990 if (xmlStrEqual(nil, BAD_CAST "true")) {
5991 if (elem->children != NULL) {
5992 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5993 return (ctxt->err);
5994 }
5995 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5996 (elemDecl->value != NULL)) {
5997 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5998 return (ctxt->err);
5999 }
6000 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006001 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006002 /* 3.3.4: 3.1 */
6003 if (nil != NULL) {
6004 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
6005 xmlFree(nil);
6006 return (ctxt->err);
6007 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006008 }
6009
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006010 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006011
6012 ctxt->type = elemDecl->subtypes;
6013 ctxt->node = elem->children;
6014 xmlSchemaValidateContent(ctxt, elem);
6015 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006016
6017 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006018}
6019
6020
6021/**
6022 * xmlSchemaValidateAttributes:
6023 * @ctxt: a schema validation context
6024 * @elem: an element
6025 * @attributes: the list of attribute declarations
6026 *
6027 * Validate the attributes of an element.
6028 *
6029 * Returns 0 if the element is schemas valid, a positive error code
6030 * number otherwise and -1 in case of internal or API error.
6031 */
6032static int
6033xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 xmlSchemaAttributePtr attributes)
6035{
Daniel Veillard4255d502002-04-16 15:50:10 +00006036 int i, ret;
6037 xmlAttrPtr attr;
6038 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006039 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006040
6041 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006042 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006043 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006044 /*
6045 * Handle attribute groups
6046 */
6047 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6048 group = (xmlSchemaAttributeGroupPtr) attributes;
6049 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6050 attributes = group->next;
6051 continue;
6052 }
6053 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6054 attr = ctxt->attr[i].attr;
6055 if (attr == NULL)
6056 continue;
6057 if (attributes->ref != NULL) {
6058 if (!xmlStrEqual(attr->name, attributes->ref))
6059 continue;
6060 if (attr->ns != NULL) {
6061 if ((attributes->refNs == NULL) ||
6062 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6063 continue;
6064 } else if (attributes->refNs != NULL) {
6065 continue;
6066 }
6067 } else {
6068 if (!xmlStrEqual(attr->name, attributes->name))
6069 continue;
6070 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006071 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006072 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006073 if (attr->ns == NULL) {
6074 /*
6075 * accept an unqualified attribute only if the declaration
6076 * is unqualified or if the schemas allowed it.
6077 */
6078 if ((attributes->targetNamespace != NULL) &&
6079 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6080 continue;
6081 } else {
6082 if (attributes->targetNamespace == NULL)
6083 continue;
6084 if (!xmlStrEqual(attributes->targetNamespace,
6085 attr->ns->href))
6086 continue;
6087 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088 }
6089 ctxt->cur = (xmlNodePtr) attributes;
6090 if (attributes->subtypes == NULL) {
6091 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6092 continue;
6093 }
6094 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6095 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6096 value);
6097 if (ret != 0) {
6098 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6099 } else {
6100 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6101 }
6102 if (value != NULL) {
6103 xmlFree(value);
6104 }
6105 }
6106 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006107 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006108 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006109}
6110
6111/**
6112 * xmlSchemaValidateElement:
6113 * @ctxt: a schema validation context
6114 * @elem: an element
6115 *
6116 * Validate an element in a tree
6117 *
6118 * Returns 0 if the element is schemas valid, a positive error code
6119 * number otherwise and -1 in case of internal or API error.
6120 */
6121static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006122xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6123{
Daniel Veillard4255d502002-04-16 15:50:10 +00006124 xmlSchemaElementPtr elemDecl;
6125 int ret, attrBase;
6126
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006127 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006128 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6129 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006130 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006131 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6132 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006133 }
6134 /*
6135 * special case whe elementFormDefault is unqualified for top-level elem.
6136 */
6137 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6138 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6139 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6140 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6141 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6142 elem->name, NULL, NULL);
6143 }
6144
Daniel Veillard4255d502002-04-16 15:50:10 +00006145 /*
6146 * 3.3.4 : 1
6147 */
6148 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006149 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6150 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006151 }
6152 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006153 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6154 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006155 }
6156 /*
6157 * Verify the attributes
6158 */
6159 attrBase = ctxt->attrBase;
6160 ctxt->attrBase = ctxt->attrNr;
6161 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6162 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6163 /*
6164 * Verify the element content recursively
6165 */
6166 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006167 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6168 (xmlRegExecCallbacks)
6169 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006170#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006171 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006172#endif
6173 }
6174 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006175 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006176 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006177#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006178 xmlGenericError(xmlGenericErrorContext,
6179 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006180#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006181 if (ret == 0) {
6182 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6183 } else if (ret < 0) {
6184 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006185#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006186 } else {
6187 xmlGenericError(xmlGenericErrorContext,
6188 "Element %s content check succeeded\n",
6189 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006190
6191#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006192 }
6193 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006194 }
6195 /*
6196 * Verify that all attributes were Schemas-validated
6197 */
6198 xmlSchemaCheckAttributes(ctxt, elem);
6199 ctxt->attrNr = ctxt->attrBase;
6200 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006201
6202 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006203}
6204
6205/**
6206 * xmlSchemaValidateDocument:
6207 * @ctxt: a schema validation context
6208 * @doc: a parsed document tree
6209 *
6210 * Validate a document tree in memory.
6211 *
6212 * Returns 0 if the document is schemas valid, a positive error code
6213 * number otherwise and -1 in case of internal or API error.
6214 */
6215static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006216xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6217{
Daniel Veillard4255d502002-04-16 15:50:10 +00006218 xmlNodePtr root;
6219 xmlSchemaElementPtr elemDecl;
6220
6221 root = xmlDocGetRootElement(doc);
6222 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006223 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6224 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006225 }
6226 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006227 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6228 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006229 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006230 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6231 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006232 /*
6233 * special case whe elementFormDefault is unqualified for top-level elem.
6234 */
6235 if ((elemDecl == NULL) && (root->ns != NULL) &&
6236 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6237 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6238 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6239 root->name, NULL, NULL);
6240 }
6241
Daniel Veillard4255d502002-04-16 15:50:10 +00006242 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006243 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006244 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006245 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006246 }
6247 /*
6248 * Okay, start the recursive validation
6249 */
6250 xmlSchemaValidateElement(ctxt, root);
6251
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006252 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006253}
6254
6255/************************************************************************
6256 * *
6257 * SAX Validation code *
6258 * *
6259 ************************************************************************/
6260
6261/************************************************************************
6262 * *
6263 * Validation interfaces *
6264 * *
6265 ************************************************************************/
6266
6267/**
6268 * xmlSchemaNewValidCtxt:
6269 * @schema: a precompiled XML Schemas
6270 *
6271 * Create an XML Schemas validation context based on the given schema
6272 *
6273 * Returns the validation context or NULL in case of error
6274 */
6275xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006276xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6277{
Daniel Veillard4255d502002-04-16 15:50:10 +00006278 xmlSchemaValidCtxtPtr ret;
6279
6280 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6281 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006282 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006283 return (NULL);
6284 }
6285 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6286 ret->schema = schema;
6287 ret->attrNr = 0;
6288 ret->attrMax = 10;
6289 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006290 sizeof
6291 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006292 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006293 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6294 free(ret);
6295 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006296 }
6297 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6298 return (ret);
6299}
6300
6301/**
6302 * xmlSchemaFreeValidCtxt:
6303 * @ctxt: the schema validation context
6304 *
6305 * Free the resources associated to the schema validation context
6306 */
6307void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006308xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6309{
Daniel Veillard4255d502002-04-16 15:50:10 +00006310 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006311 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006312 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006313 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006314 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006315 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006316 xmlFree(ctxt);
6317}
6318
6319/**
6320 * xmlSchemaSetValidErrors:
6321 * @ctxt: a schema validation context
6322 * @err: the error function
6323 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006324 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006325 *
6326 * Set the error and warning callback informations
6327 */
6328void
6329xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006330 xmlSchemaValidityErrorFunc err,
6331 xmlSchemaValidityWarningFunc warn, void *ctx)
6332{
Daniel Veillard4255d502002-04-16 15:50:10 +00006333 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006334 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006335 ctxt->error = err;
6336 ctxt->warning = warn;
6337 ctxt->userData = ctx;
6338}
6339
6340/**
6341 * xmlSchemaValidateDoc:
6342 * @ctxt: a schema validation context
6343 * @doc: a parsed document tree
6344 *
6345 * Validate a document tree in memory.
6346 *
6347 * Returns 0 if the document is schemas valid, a positive error code
6348 * number otherwise and -1 in case of internal or API error.
6349 */
6350int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006351xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6352{
Daniel Veillard4255d502002-04-16 15:50:10 +00006353 int ret;
6354
6355 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006356 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006357
6358 ctxt->doc = doc;
6359 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006360 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006361}
6362
6363/**
6364 * xmlSchemaValidateStream:
6365 * @ctxt: a schema validation context
6366 * @input: the input to use for reading the data
6367 * @enc: an optional encoding information
6368 * @sax: a SAX handler for the resulting events
6369 * @user_data: the context to provide to the SAX handler.
6370 *
6371 * Validate a document tree in memory.
6372 *
6373 * Returns 0 if the document is schemas valid, a positive error code
6374 * number otherwise and -1 in case of internal or API error.
6375 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006376int
Daniel Veillard4255d502002-04-16 15:50:10 +00006377xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006378 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6379 xmlSAXHandlerPtr sax, void *user_data)
6380{
Daniel Veillard4255d502002-04-16 15:50:10 +00006381 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006382 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006383 ctxt->input = input;
6384 ctxt->enc = enc;
6385 ctxt->sax = sax;
6386 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006387 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006388}
6389
6390#endif /* LIBXML_SCHEMAS_ENABLED */