blob: d639b67f3ad3803a83bf2d1ce3f3f0a47cd42bbb [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 Veillard4255d502002-04-16 15:50:10 +000088
Daniel Veillardd0c9c322003-10-10 00:49:42 +000089 const char *buffer;
90 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +000091
Daniel Veillard4255d502002-04-16 15:50:10 +000092 /*
93 * Used to build complex element content models
94 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000095 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +000096 xmlAutomataStatePtr start;
97 xmlAutomataStatePtr end;
98 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000099
100 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000101 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard4255d502002-04-16 15:50:10 +0000102};
103
104
105#define XML_SCHEMAS_ATTR_UNKNOWN 1
106#define XML_SCHEMAS_ATTR_CHECKED 2
107
108typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
109typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
110struct _xmlSchemaAttrState {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000111 xmlAttrPtr attr;
112 int state;
Daniel Veillard4255d502002-04-16 15:50:10 +0000113};
114
115/**
116 * xmlSchemaValidCtxt:
117 *
118 * A Schemas validation context
119 */
120
121struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000122 void *userData; /* user specific data block */
123 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
124 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000125 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000126
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000127 xmlSchemaPtr schema; /* The schema in use */
128 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000129 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000130 xmlCharEncoding enc;
131 xmlSAXHandlerPtr sax;
132 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000133
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000134 xmlDocPtr myDoc;
135 int err;
136 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000137
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000138 xmlNodePtr node;
139 xmlNodePtr cur;
140 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000141
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000142 xmlRegExecCtxtPtr regexp;
143 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000144
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000145 int attrNr;
146 int attrBase;
147 int attrMax;
148 xmlSchemaAttrStatePtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +0000149};
150
Daniel Veillard1d913862003-11-21 00:28:39 +0000151/*
152 * These are the entries in the schemas importSchemas hash table
153 */
154typedef struct _xmlSchemaImport xmlSchemaImport;
155typedef xmlSchemaImport *xmlSchemaImportPtr;
156struct _xmlSchemaImport {
157 const xmlChar *schemaLocation;
158 xmlSchemaPtr schema;
159};
Daniel Veillard4255d502002-04-16 15:50:10 +0000160
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000161/*
162 * These are the entries associated to includes in a schemas
163 */
164typedef struct _xmlSchemaInclude xmlSchemaInclude;
165typedef xmlSchemaInclude *xmlSchemaIncludePtr;
166struct _xmlSchemaInclude {
167 xmlSchemaIncludePtr next;
168
169 const xmlChar *schemaLocation;
170 xmlDocPtr doc;
171};
172
Daniel Veillard4255d502002-04-16 15:50:10 +0000173/************************************************************************
174 * *
175 * Some predeclarations *
176 * *
177 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000178static int xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
179 xmlSchemaTypePtr type,
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000180 const xmlChar * value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000181
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000182static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
183 xmlSchemaPtr schema,
184 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000185/************************************************************************
186 * *
187 * Datatype error handlers *
188 * *
189 ************************************************************************/
190
191/**
192 * xmlSchemaPErrMemory:
193 * @node: a context node
194 * @extra: extra informations
195 *
196 * Handle an out of memory condition
197 */
198static void
199xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
200 const char *extra, xmlNodePtr node)
201{
202 if (ctxt != NULL)
203 ctxt->nberrors++;
204 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
205 extra);
206}
207
208/**
209 * xmlSchemaPErr:
210 * @ctxt: the parsing context
211 * @node: the context node
212 * @error: the error code
213 * @msg: the error message
214 * @str1: extra data
215 * @str2: extra data
216 *
217 * Handle a parser error
218 */
219static void
220xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
221 const char *msg, const xmlChar * str1, const xmlChar * str2)
222{
223 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000224 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000225 void *data = NULL;
226
227 if (ctxt != NULL) {
228 ctxt->nberrors++;
229 channel = ctxt->error;
230 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000231 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000232 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000233 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 error, XML_ERR_ERROR, NULL, 0,
235 (const char *) str1, (const char *) str2, NULL, 0, 0,
236 msg, str1, str2);
237}
238
239/**
240 * xmlSchemaPErr2:
241 * @ctxt: the parsing context
242 * @node: the context node
243 * @node: the current child
244 * @error: the error code
245 * @msg: the error message
246 * @str1: extra data
247 * @str2: extra data
248 *
249 * Handle a parser error
250 */
251static void
252xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
253 xmlNodePtr child, int error,
254 const char *msg, const xmlChar * str1, const xmlChar * str2)
255{
256 if (child != NULL)
257 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
258 else
259 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
260}
261
262/**
263 * xmlSchemaVTypeErrMemory:
264 * @node: a context node
265 * @extra: extra informations
266 *
267 * Handle an out of memory condition
268 */
269static void
270xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
271 const char *extra, xmlNodePtr node)
272{
273 if (ctxt != NULL) {
274 ctxt->nberrors++;
275 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
276 }
277 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
278 extra);
279}
280
281/**
282 * xmlSchemaVErr3:
283 * @ctxt: the validation context
284 * @node: the context node
285 * @error: the error code
286 * @msg: the error message
287 * @str1: extra data
288 * @str2: extra data
289 * @str3: extra data
290 *
291 * Handle a validation error
292 */
293static void
294xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
295 const char *msg, const xmlChar *str1, const xmlChar *str2,
296 const xmlChar *str3)
297{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000298 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000299 xmlGenericErrorFunc channel = NULL;
300 void *data = NULL;
301
302 if (ctxt != NULL) {
303 ctxt->nberrors++;
304 ctxt->err = error;
305 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000306 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000307 data = ctxt->userData;
308 }
309 /* reajust to global error numbers */
310 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000311 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000312 error, XML_ERR_ERROR, NULL, 0,
313 (const char *) str1, (const char *) str2,
314 (const char *) str3, 0, 0,
315 msg, str1, str2, str3);
316}
317/**
318 * xmlSchemaVErr:
319 * @ctxt: the validation context
320 * @node: the context node
321 * @error: the error code
322 * @msg: the error message
323 * @str1: extra data
324 * @str2: extra data
325 *
326 * Handle a validation error
327 */
328static void
329xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
330 const char *msg, const xmlChar * str1, const xmlChar * str2)
331{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000332 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000333 xmlGenericErrorFunc channel = NULL;
334 void *data = NULL;
335
336 if (ctxt != NULL) {
337 ctxt->nberrors++;
338 ctxt->err = error;
339 channel = ctxt->error;
340 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000341 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000342 }
343 /* reajust to global error numbers */
344 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000345 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000346 error, XML_ERR_ERROR, NULL, 0,
347 (const char *) str1, (const char *) str2, NULL, 0, 0,
348 msg, str1, str2);
349}
Daniel Veillard4255d502002-04-16 15:50:10 +0000350
351/************************************************************************
352 * *
353 * Allocation functions *
354 * *
355 ************************************************************************/
356
357/**
358 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +0000359 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000360 *
361 * Allocate a new Schema structure.
362 *
363 * Returns the newly allocated structure or NULL in case or error
364 */
365static xmlSchemaPtr
366xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
367{
368 xmlSchemaPtr ret;
369
370 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
371 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000372 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +0000373 return (NULL);
374 }
375 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000376 xmlDictReference(ctxt->dict);
377 ret->dict = ctxt->dict;
Daniel Veillard4255d502002-04-16 15:50:10 +0000378
379 return (ret);
380}
381
382/**
383 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +0000384 *
385 * Allocate a new Facet structure.
386 *
387 * Returns the newly allocated structure or NULL in case or error
388 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000389xmlSchemaFacetPtr
390xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +0000391{
392 xmlSchemaFacetPtr ret;
393
394 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
395 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +0000396 return (NULL);
397 }
398 memset(ret, 0, sizeof(xmlSchemaFacet));
399
400 return (ret);
401}
402
403/**
404 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +0000405 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +0000406 * @node: a node
407 *
408 * Allocate a new annotation structure.
409 *
410 * Returns the newly allocated structure or NULL in case or error
411 */
412static xmlSchemaAnnotPtr
413xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
414{
415 xmlSchemaAnnotPtr ret;
416
417 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
418 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000419 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +0000420 return (NULL);
421 }
422 memset(ret, 0, sizeof(xmlSchemaAnnot));
423 ret->content = node;
424 return (ret);
425}
426
427/**
Daniel Veillardfdc91562002-07-01 21:52:03 +0000428 * xmlSchemaFreeAnnot:
429 * @annot: a schema type structure
430 *
431 * Deallocate a annotation structure
432 */
433static void
434xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
435{
436 if (annot == NULL)
437 return;
438 xmlFree(annot);
439}
440
441/**
Daniel Veillard1d913862003-11-21 00:28:39 +0000442 * xmlSchemaFreeImport:
443 * @import: a schema import structure
444 *
445 * Deallocate an import structure
446 */
447static void
448xmlSchemaFreeImport(xmlSchemaImportPtr import)
449{
450 if (import == NULL)
451 return;
452
453 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +0000454 xmlFree(import);
455}
456
457/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000458 * xmlSchemaFreeInclude:
459 * @include: a schema include structure
460 *
461 * Deallocate an include structure
462 */
463static void
464xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
465{
466 if (include == NULL)
467 return;
468
469 xmlFreeDoc(include->doc);
470 xmlFree(include);
471}
472
473/**
474 * xmlSchemaFreeIncludeList:
475 * @includes: a schema include list
476 *
477 * Deallocate an include structure
478 */
479static void
480xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
481{
482 xmlSchemaIncludePtr next;
483
484 while (includes != NULL) {
485 next = includes->next;
486 xmlSchemaFreeInclude(includes);
487 includes = next;
488 }
489}
490
491/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000492 * xmlSchemaFreeNotation:
493 * @schema: a schema notation structure
494 *
495 * Deallocate a Schema Notation structure.
496 */
497static void
498xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
499{
500 if (nota == NULL)
501 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000502 xmlFree(nota);
503}
504
505/**
506 * xmlSchemaFreeAttribute:
507 * @schema: a schema attribute structure
508 *
509 * Deallocate a Schema Attribute structure.
510 */
511static void
512xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
513{
514 if (attr == NULL)
515 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000516 xmlFree(attr);
517}
518
519/**
520 * xmlSchemaFreeAttributeGroup:
521 * @schema: a schema attribute group structure
522 *
523 * Deallocate a Schema Attribute Group structure.
524 */
525static void
526xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
527{
528 if (attr == NULL)
529 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000530 xmlFree(attr);
531}
532
533/**
534 * xmlSchemaFreeElement:
535 * @schema: a schema element structure
536 *
537 * Deallocate a Schema Element structure.
538 */
539static void
540xmlSchemaFreeElement(xmlSchemaElementPtr elem)
541{
542 if (elem == NULL)
543 return;
Daniel Veillard32370232002-10-16 14:08:14 +0000544 if (elem->annot != NULL)
545 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000546 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000547 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +0000548 xmlFree(elem);
549}
550
551/**
552 * xmlSchemaFreeFacet:
553 * @facet: a schema facet structure
554 *
555 * Deallocate a Schema Facet structure.
556 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +0000557void
Daniel Veillard4255d502002-04-16 15:50:10 +0000558xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
559{
560 if (facet == NULL)
561 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000562 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000563 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +0000564 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000565 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000566 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000567 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000568 xmlFree(facet);
569}
570
571/**
572 * xmlSchemaFreeType:
573 * @type: a schema type structure
574 *
575 * Deallocate a Schema Type structure.
576 */
577void
578xmlSchemaFreeType(xmlSchemaTypePtr type)
579{
580 if (type == NULL)
581 return;
Daniel Veillard4255d502002-04-16 15:50:10 +0000582 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +0000583 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000584 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000585 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +0000586
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000587 facet = type->facets;
588 while (facet != NULL) {
589 next = facet->next;
590 xmlSchemaFreeFacet(facet);
591 facet = next;
592 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000593 }
594 xmlFree(type);
595}
596
597/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000598 * xmlSchemaFreeTypeList:
599 * @type: a schema type structure
600 *
601 * Deallocate a Schema Type structure.
602 */
603static void
604xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
605{
606 xmlSchemaTypePtr next;
607
608 while (type != NULL) {
609 next = type->redef;
610 xmlSchemaFreeType(type);
611 type = next;
612 }
613}
614
615/**
Daniel Veillard4255d502002-04-16 15:50:10 +0000616 * xmlSchemaFree:
617 * @schema: a schema structure
618 *
619 * Deallocate a Schema structure.
620 */
621void
622xmlSchemaFree(xmlSchemaPtr schema)
623{
624 if (schema == NULL)
625 return;
626
Daniel Veillard4255d502002-04-16 15:50:10 +0000627 if (schema->notaDecl != NULL)
628 xmlHashFree(schema->notaDecl,
629 (xmlHashDeallocator) xmlSchemaFreeNotation);
630 if (schema->attrDecl != NULL)
631 xmlHashFree(schema->attrDecl,
632 (xmlHashDeallocator) xmlSchemaFreeAttribute);
633 if (schema->attrgrpDecl != NULL)
634 xmlHashFree(schema->attrgrpDecl,
635 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
636 if (schema->elemDecl != NULL)
637 xmlHashFree(schema->elemDecl,
638 (xmlHashDeallocator) xmlSchemaFreeElement);
639 if (schema->typeDecl != NULL)
640 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000641 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +0000642 if (schema->groupDecl != NULL)
643 xmlHashFree(schema->groupDecl,
644 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +0000645 if (schema->schemasImports != NULL)
646 xmlHashFree(schema->schemasImports,
647 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000648 if (schema->includes != NULL) {
649 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
650 }
Daniel Veillard4255d502002-04-16 15:50:10 +0000651 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000652 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +0000653 if (schema->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000654 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000655 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +0000656
657 xmlFree(schema);
658}
659
660/************************************************************************
661 * *
Daniel Veillard4255d502002-04-16 15:50:10 +0000662 * Debug functions *
663 * *
664 ************************************************************************/
665
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000666#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000667
Daniel Veillard4255d502002-04-16 15:50:10 +0000668/**
669 * xmlSchemaElementDump:
670 * @elem: an element
671 * @output: the file output
672 *
673 * Dump the element
674 */
675static void
676xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000677 const xmlChar * name ATTRIBUTE_UNUSED,
678 const xmlChar * context ATTRIBUTE_UNUSED,
679 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +0000680{
681 if (elem == NULL)
682 return;
683
684 fprintf(output, "Element ");
685 if (elem->flags & XML_SCHEMAS_ELEM_TOPLEVEL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000686 fprintf(output, "toplevel ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000687 fprintf(output, ": %s ", elem->name);
688 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000689 fprintf(output, "namespace '%s' ", namespace);
690
Daniel Veillard4255d502002-04-16 15:50:10 +0000691 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000692 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000693 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000694 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000695 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000696 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000697 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000698 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000699 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000700 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +0000701 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000702 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +0000703 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000704 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +0000705 fprintf(output, "\n");
706 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000707 fprintf(output, " ");
708 if (elem->minOccurs != 1)
709 fprintf(output, "min: %d ", elem->minOccurs);
710 if (elem->maxOccurs >= UNBOUNDED)
711 fprintf(output, "max: unbounded\n");
712 else if (elem->maxOccurs != 1)
713 fprintf(output, "max: %d\n", elem->maxOccurs);
714 else
715 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000716 }
717 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000718 fprintf(output, " type: %s", elem->namedType);
719 if (elem->namedTypeNs != NULL)
720 fprintf(output, " ns %s\n", elem->namedTypeNs);
721 else
722 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000723 }
724 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000725 fprintf(output, " substitutionGroup: %s", elem->substGroup);
726 if (elem->substGroupNs != NULL)
727 fprintf(output, " ns %s\n", elem->substGroupNs);
728 else
729 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000730 }
731 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000732 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +0000733}
734
735/**
736 * xmlSchemaAnnotDump:
737 * @output: the file output
738 * @annot: a annotation
739 *
740 * Dump the annotation
741 */
742static void
743xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
744{
745 xmlChar *content;
746
747 if (annot == NULL)
748 return;
749
750 content = xmlNodeGetContent(annot->content);
751 if (content != NULL) {
752 fprintf(output, " Annot: %s\n", content);
753 xmlFree(content);
754 } else
755 fprintf(output, " Annot: empty\n");
756}
757
758/**
759 * xmlSchemaTypeDump:
760 * @output: the file output
761 * @type: a type structure
762 *
763 * Dump a SchemaType structure
764 */
765static void
766xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
767{
768 if (type == NULL) {
769 fprintf(output, "Type: NULL\n");
770 return;
771 }
772 fprintf(output, "Type: ");
773 if (type->name != NULL)
774 fprintf(output, "%s, ", type->name);
775 else
776 fprintf(output, "no name");
777 switch (type->type) {
778 case XML_SCHEMA_TYPE_BASIC:
779 fprintf(output, "basic ");
780 break;
781 case XML_SCHEMA_TYPE_SIMPLE:
782 fprintf(output, "simple ");
783 break;
784 case XML_SCHEMA_TYPE_COMPLEX:
785 fprintf(output, "complex ");
786 break;
787 case XML_SCHEMA_TYPE_SEQUENCE:
788 fprintf(output, "sequence ");
789 break;
790 case XML_SCHEMA_TYPE_CHOICE:
791 fprintf(output, "choice ");
792 break;
793 case XML_SCHEMA_TYPE_ALL:
794 fprintf(output, "all ");
795 break;
796 case XML_SCHEMA_TYPE_UR:
797 fprintf(output, "ur ");
798 break;
799 case XML_SCHEMA_TYPE_RESTRICTION:
800 fprintf(output, "restriction ");
801 break;
802 case XML_SCHEMA_TYPE_EXTENSION:
803 fprintf(output, "extension ");
804 break;
805 default:
806 fprintf(output, "unknowntype%d ", type->type);
807 break;
808 }
809 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000810 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +0000811 }
812 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000813 case XML_SCHEMA_CONTENT_UNKNOWN:
814 fprintf(output, "unknown ");
815 break;
816 case XML_SCHEMA_CONTENT_EMPTY:
817 fprintf(output, "empty ");
818 break;
819 case XML_SCHEMA_CONTENT_ELEMENTS:
820 fprintf(output, "element ");
821 break;
822 case XML_SCHEMA_CONTENT_MIXED:
823 fprintf(output, "mixed ");
824 break;
825 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
826 fprintf(output, "mixed_or_elems ");
827 break;
828 case XML_SCHEMA_CONTENT_BASIC:
829 fprintf(output, "basic ");
830 break;
831 case XML_SCHEMA_CONTENT_SIMPLE:
832 fprintf(output, "simple ");
833 break;
834 case XML_SCHEMA_CONTENT_ANY:
835 fprintf(output, "any ");
836 break;
Daniel Veillard4255d502002-04-16 15:50:10 +0000837 }
838 fprintf(output, "\n");
839 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000840 fprintf(output, " ");
841 if (type->minOccurs != 1)
842 fprintf(output, "min: %d ", type->minOccurs);
843 if (type->maxOccurs >= UNBOUNDED)
844 fprintf(output, "max: unbounded\n");
845 else if (type->maxOccurs != 1)
846 fprintf(output, "max: %d\n", type->maxOccurs);
847 else
848 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000849 }
850 if (type->annot != NULL)
851 xmlSchemaAnnotDump(output, type->annot);
852 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000853 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +0000854
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000855 fprintf(output, " subtypes: ");
856 while (sub != NULL) {
857 fprintf(output, "%s ", sub->name);
858 sub = sub->next;
859 }
860 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +0000861 }
862
863}
864
865/**
866 * xmlSchemaDump:
867 * @output: the file output
868 * @schema: a schema structure
869 *
870 * Dump a Schema structure.
871 */
872void
873xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
874{
875 if (schema == NULL) {
876 fprintf(output, "Schemas: NULL\n");
877 return;
878 }
879 fprintf(output, "Schemas: ");
880 if (schema->name != NULL)
881 fprintf(output, "%s, ", schema->name);
882 else
883 fprintf(output, "no name, ");
884 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +0000885 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +0000886 else
887 fprintf(output, "no target namespace");
888 fprintf(output, "\n");
889 if (schema->annot != NULL)
890 xmlSchemaAnnotDump(output, schema->annot);
891
892 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
893 output);
894 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000895 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +0000896}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000897#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +0000898
899/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000900 * *
901 * Utilities *
902 * *
903 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000904
905/**
906 * xmlSchemaGetProp:
907 * @ctxt: the parser context
908 * @node: the node
909 * @name: the property name
910 *
911 * Read a attribute value and internalize the string
912 *
913 * Returns the string or NULL if not present.
914 */
915static const xmlChar *
916xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
917 const char *name)
918{
919 xmlChar *val;
920 const xmlChar *ret;
921
922 val = xmlGetProp(node, BAD_CAST name);
923 if (val == NULL)
924 return(NULL);
925 ret = xmlDictLookup(ctxt->dict, val, -1);
926 xmlFree(val);
927 return(ret);
928}
929
930/**
931 * xmlSchemaGetNamespace:
932 * @ctxt: the parser context
933 * @schema: the schemas containing the declaration
934 * @node: the node
935 * @qname: the QName to analyze
936 *
937 * Find the namespace name for the given declaration.
938 *
939 * Returns the local name for that declaration, as well as the namespace name
940 */
941static const xmlChar *
942xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
943 xmlNodePtr node, const xmlChar *qname,
944 const xmlChar **namespace) {
945 int len;
946 const xmlChar *name, *prefix, *def = NULL;
947 xmlNsPtr ns;
948
949 *namespace = NULL;
950
951 if (xmlStrEqual(node->name, BAD_CAST "element") ||
952 xmlStrEqual(node->name, BAD_CAST "attribute") ||
953 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
954 xmlStrEqual(node->name, BAD_CAST "complexType")) {
955 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
956 }
957
958 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
959 name = xmlSplitQName3(qname, &len);
960 if (name == NULL) {
961 if (def == NULL) {
962 if (xmlStrEqual(node->name, BAD_CAST "element")) {
963 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
964 *namespace = schema->targetNamespace;
965 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
966 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
967 *namespace = schema->targetNamespace;
968 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
969 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
970 *namespace = schema->targetNamespace;
971 }
972 } else {
973 *namespace = def;
974 }
975 return(qname);
976 }
977 name = xmlDictLookup(ctxt->dict, name, -1);
978 prefix = xmlDictLookup(ctxt->dict, qname, len);
979 if (def != NULL) {
980 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
981 "%s: presence of both prefix %s and targetNamespace\n",
982 node->name, prefix);
983 }
984 ns = xmlSearchNs(node->doc, node, prefix);
985 if (ns == NULL) {
986 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
987 "%s: the QName prefix %s is undefined\n",
988 node->name, prefix);
989 return(name);
990 }
991 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
992 return(name);
993}
994
995/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +0000996 * *
997 * Parsing functions *
998 * *
999 ************************************************************************/
1000
1001/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001002 * xmlSchemaGetElem:
1003 * @schema: the schemas context
1004 * @name: the element name
1005 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001006 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001007 *
1008 * Lookup a an element in the schemas or the accessible schemas
1009 *
1010 * Returns the element definition or NULL if not found.
1011 */
1012static xmlSchemaElementPtr
1013xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001014 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001015{
1016 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001017 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001018
1019 if ((name == NULL) || (schema == NULL))
1020 return (NULL);
1021
1022 if (namespace == NULL) {
1023 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001024 if ((ret != NULL) &&
1025 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001026 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001027 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001028 } else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
1029 if (xmlStrEqual(namespace, schema->targetNamespace))
1030 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1031 else
1032 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001033 if ((ret != NULL) &&
1034 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001035 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001036 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001037 } else {
1038 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001039 if ((ret != NULL) &&
1040 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001041 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001042 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001043 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00001044 if (level > 0)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001045 import = xmlHashLookup(schema->schemasImports, namespace);
1046 if (import != NULL)
Daniel Veillardf2a12832003-11-24 13:04:35 +00001047 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001048#ifdef DEBUG
1049 if (ret == NULL) {
1050 if (namespace == NULL)
1051 fprintf(stderr, "Unable to lookup type %s", name);
1052 else
1053 fprintf(stderr, "Unable to lookup type %s:%s", name,
1054 namespace);
1055 }
1056#endif
1057 return (ret);
1058}
1059
1060/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001061 * xmlSchemaGetType:
1062 * @schema: the schemas context
1063 * @name: the type name
1064 * @ns: the type namespace
1065 *
1066 * Lookup a type in the schemas or the predefined types
1067 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001068 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001069 */
1070static xmlSchemaTypePtr
1071xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001072 const xmlChar * namespace)
1073{
Daniel Veillard4255d502002-04-16 15:50:10 +00001074 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001075 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001076
1077 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001078 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001079 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001080 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
1081 if (ret != NULL)
1082 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001083 }
1084 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001085 if (ret != NULL)
1086 return (ret);
1087 import = xmlHashLookup(schema->schemasImports, namespace);
1088 if (import != NULL)
1089 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001090#ifdef DEBUG
1091 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001092 if (namespace == NULL)
1093 fprintf(stderr, "Unable to lookup type %s", name);
1094 else
1095 fprintf(stderr, "Unable to lookup type %s:%s", name,
1096 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001097 }
1098#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001099 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001100}
1101
1102/************************************************************************
1103 * *
1104 * Parsing functions *
1105 * *
1106 ************************************************************************/
1107
1108#define IS_BLANK_NODE(n) \
1109 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1110
1111/**
1112 * xmlSchemaIsBlank:
1113 * @str: a string
1114 *
1115 * Check if a string is ignorable
1116 *
1117 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1118 */
1119static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001120xmlSchemaIsBlank(xmlChar * str)
1121{
Daniel Veillard4255d502002-04-16 15:50:10 +00001122 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001123 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001124 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001125 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001126 return (0);
1127 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001128 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001129 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001130}
1131
1132/**
1133 * xmlSchemaAddNotation:
1134 * @ctxt: a schema validation context
1135 * @schema: the schema being built
1136 * @name: the item name
1137 *
1138 * Add an XML schema Attrribute declaration
1139 * *WARNING* this interface is highly subject to change
1140 *
1141 * Returns the new struture or NULL in case of error
1142 */
1143static xmlSchemaNotationPtr
1144xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001145 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001146{
1147 xmlSchemaNotationPtr ret = NULL;
1148 int val;
1149
1150 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1151 return (NULL);
1152
1153 if (schema->notaDecl == NULL)
1154 schema->notaDecl = xmlHashCreate(10);
1155 if (schema->notaDecl == NULL)
1156 return (NULL);
1157
1158 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1159 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001160 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001161 return (NULL);
1162 }
1163 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001164 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001165 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1166 ret);
1167 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001168 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1169 XML_SCHEMAP_REDEFINED_NOTATION,
1170 "Notation %s already defined\n",
1171 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001172 xmlFree(ret);
1173 return (NULL);
1174 }
1175 return (ret);
1176}
1177
1178
1179/**
1180 * xmlSchemaAddAttribute:
1181 * @ctxt: a schema validation context
1182 * @schema: the schema being built
1183 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001184 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001185 *
1186 * Add an XML schema Attrribute declaration
1187 * *WARNING* this interface is highly subject to change
1188 *
1189 * Returns the new struture or NULL in case of error
1190 */
1191static xmlSchemaAttributePtr
1192xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001193 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001194{
1195 xmlSchemaAttributePtr ret = NULL;
1196 int val;
1197
1198 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1199 return (NULL);
1200
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001201#ifdef DEBUG
1202 fprintf(stderr, "Adding attribute %s\n", name);
1203 if (namespace != NULL)
1204 fprintf(stderr, " target namespace %s\n", namespace);
1205#endif
1206
Daniel Veillard4255d502002-04-16 15:50:10 +00001207 if (schema->attrDecl == NULL)
1208 schema->attrDecl = xmlHashCreate(10);
1209 if (schema->attrDecl == NULL)
1210 return (NULL);
1211
1212 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1213 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001214 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001215 return (NULL);
1216 }
1217 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001218 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1219 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001220 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001221 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001222 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001223 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1224 XML_SCHEMAP_REDEFINED_ATTR,
1225 "Attribute %s already defined\n",
1226 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001227 xmlFree(ret);
1228 return (NULL);
1229 }
1230 return (ret);
1231}
1232
1233/**
1234 * xmlSchemaAddAttributeGroup:
1235 * @ctxt: a schema validation context
1236 * @schema: the schema being built
1237 * @name: the item name
1238 *
1239 * Add an XML schema Attrribute Group declaration
1240 *
1241 * Returns the new struture or NULL in case of error
1242 */
1243static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001244xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1245 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001246{
1247 xmlSchemaAttributeGroupPtr ret = NULL;
1248 int val;
1249
1250 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1251 return (NULL);
1252
1253 if (schema->attrgrpDecl == NULL)
1254 schema->attrgrpDecl = xmlHashCreate(10);
1255 if (schema->attrgrpDecl == NULL)
1256 return (NULL);
1257
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001258 ret =
1259 (xmlSchemaAttributeGroupPtr)
1260 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001261 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001262 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001263 return (NULL);
1264 }
1265 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001266 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001267 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001268 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001269 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001270 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1271 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1272 "Attribute group %s already defined\n",
1273 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001274 xmlFree(ret);
1275 return (NULL);
1276 }
1277 return (ret);
1278}
1279
1280/**
1281 * xmlSchemaAddElement:
1282 * @ctxt: a schema validation context
1283 * @schema: the schema being built
1284 * @name: the type name
1285 * @namespace: the type namespace
1286 *
1287 * Add an XML schema Element declaration
1288 * *WARNING* this interface is highly subject to change
1289 *
1290 * Returns the new struture or NULL in case of error
1291 */
1292static xmlSchemaElementPtr
1293xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1294 const xmlChar * name, const xmlChar * namespace)
1295{
1296 xmlSchemaElementPtr ret = NULL;
1297 int val;
1298
1299 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1300 return (NULL);
1301
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001302#ifdef DEBUG
1303 fprintf(stderr, "Adding element %s\n", name);
1304 if (namespace != NULL)
1305 fprintf(stderr, " target namespace %s\n", namespace);
1306#endif
1307
Daniel Veillard4255d502002-04-16 15:50:10 +00001308 if (schema->elemDecl == NULL)
1309 schema->elemDecl = xmlHashCreate(10);
1310 if (schema->elemDecl == NULL)
1311 return (NULL);
1312
1313 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1314 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001315 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001316 return (NULL);
1317 }
1318 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001319 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1320 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001321 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001322 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001323 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001324 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001325
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001326 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001327 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1328 namespace, ret);
1329 if (val != 0) {
1330 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1331 XML_SCHEMAP_REDEFINED_ELEMENT,
1332 "Element %s already defined\n",
1333 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001334 xmlFree(ret);
1335 return (NULL);
1336 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001337 }
1338 return (ret);
1339}
1340
1341/**
1342 * xmlSchemaAddType:
1343 * @ctxt: a schema validation context
1344 * @schema: the schema being built
1345 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001346 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001347 *
1348 * Add an XML schema Simple Type definition
1349 * *WARNING* this interface is highly subject to change
1350 *
1351 * Returns the new struture or NULL in case of error
1352 */
1353static xmlSchemaTypePtr
1354xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001355 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001356{
1357 xmlSchemaTypePtr ret = NULL;
1358 int val;
1359
1360 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1361 return (NULL);
1362
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001363#ifdef DEBUG
1364 fprintf(stderr, "Adding type %s\n", name);
1365 if (namespace != NULL)
1366 fprintf(stderr, " target namespace %s\n", namespace);
1367#endif
1368
Daniel Veillard4255d502002-04-16 15:50:10 +00001369 if (schema->typeDecl == NULL)
1370 schema->typeDecl = xmlHashCreate(10);
1371 if (schema->typeDecl == NULL)
1372 return (NULL);
1373
1374 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1375 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001376 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001377 return (NULL);
1378 }
1379 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001380 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001381 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001382 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001383 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001384 if (ctxt->includes == 0) {
1385 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1386 XML_SCHEMAP_REDEFINED_TYPE,
1387 "Type %s already defined\n",
1388 name, NULL);
1389 xmlFree(ret);
1390 return (NULL);
1391 } else {
1392 xmlSchemaTypePtr prev;
1393
1394 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1395 if (prev == NULL) {
1396 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1397 XML_ERR_INTERNAL_ERROR,
1398 "Internal error on type %s definition\n",
1399 name, NULL);
1400 xmlFree(ret);
1401 return (NULL);
1402 }
1403 ret->redef = prev->redef;
1404 prev->redef = ret;
1405 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001406 }
1407 ret->minOccurs = 1;
1408 ret->maxOccurs = 1;
1409
1410 return (ret);
1411}
1412
1413/**
1414 * xmlSchemaAddGroup:
1415 * @ctxt: a schema validation context
1416 * @schema: the schema being built
1417 * @name: the group name
1418 *
1419 * Add an XML schema Group definition
1420 *
1421 * Returns the new struture or NULL in case of error
1422 */
1423static xmlSchemaTypePtr
1424xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001425 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001426{
1427 xmlSchemaTypePtr ret = NULL;
1428 int val;
1429
1430 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1431 return (NULL);
1432
1433 if (schema->groupDecl == NULL)
1434 schema->groupDecl = xmlHashCreate(10);
1435 if (schema->groupDecl == NULL)
1436 return (NULL);
1437
1438 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1439 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001440 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001441 return (NULL);
1442 }
1443 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001444 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 val =
1446 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
1447 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001448 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001449 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1450 XML_SCHEMAP_REDEFINED_GROUP,
1451 "Group %s already defined\n",
1452 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001453 xmlFree(ret);
1454 return (NULL);
1455 }
1456 ret->minOccurs = 1;
1457 ret->maxOccurs = 1;
1458
1459 return (ret);
1460}
1461
1462/************************************************************************
1463 * *
1464 * Utilities for parsing *
1465 * *
1466 ************************************************************************/
1467
1468/**
1469 * xmlGetQNameProp:
1470 * @ctxt: a schema validation context
1471 * @node: a subtree containing XML Schema informations
1472 * @name: the attribute name
1473 * @namespace: the result namespace if any
1474 *
1475 * Extract a QName Attribute value
1476 *
1477 * Returns the NCName or NULL if not found, and also update @namespace
1478 * with the namespace URI
1479 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001480static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00001481xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001482 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001484 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001485 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001486 const xmlChar *ret, *prefix;
1487 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00001488
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001489 *namespace = NULL;
1490 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001491 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001492 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001493
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001494 ret = xmlSplitQName3(val, &len);
1495 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001496 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001497 }
1498 ret = xmlDictLookup(ctxt->dict, ret, -1);
1499 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00001500
1501 ns = xmlSearchNs(node->doc, node, prefix);
1502 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001503 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1504 "Attribute %s: the QName prefix %s is undefined\n",
1505 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00001506 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001507 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001508 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001509 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001510}
1511
1512/**
1513 * xmlGetMaxOccurs:
1514 * @ctxt: a schema validation context
1515 * @node: a subtree containing XML Schema informations
1516 *
1517 * Get the maxOccurs property
1518 *
1519 * Returns the default if not found, or the value
1520 */
1521static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001522xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1523{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001524 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001525 int ret = 0;
1526
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001527 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001528 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001529 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001530
1531 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001532 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00001533 }
1534
1535 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001536 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001537 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001538 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001539 ret = ret * 10 + (*cur - '0');
1540 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001541 }
William M. Brack76e95df2003-10-18 16:20:14 +00001542 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001543 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001544 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
1546 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001547 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001548 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001549 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001550}
1551
1552/**
1553 * xmlGetMinOccurs:
1554 * @ctxt: a schema validation context
1555 * @node: a subtree containing XML Schema informations
1556 *
1557 * Get the minOccurs property
1558 *
1559 * Returns the default if not found, or the value
1560 */
1561static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001562xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1563{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001564 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00001565 int ret = 0;
1566
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001567 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00001568 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001569 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001570
1571 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00001572 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001573 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001574 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001575 ret = ret * 10 + (*cur - '0');
1576 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001577 }
William M. Brack76e95df2003-10-18 16:20:14 +00001578 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001579 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001580 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001581 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
1582 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001583 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001584 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001585 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001586}
1587
1588/**
1589 * xmlGetBooleanProp:
1590 * @ctxt: a schema validation context
1591 * @node: a subtree containing XML Schema informations
1592 * @name: the attribute name
1593 * @def: the default value
1594 *
1595 * Get is a bolean property is set
1596 *
1597 * Returns the default if not found, 0 if found to be false,
1598 * 1 if found to be true
1599 */
1600static int
1601xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001602 const char *name, int def)
1603{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001604 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00001605
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001606 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00001607 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001608 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001609
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001610 if (xmlStrEqual(val, BAD_CAST "true"))
1611 def = 1;
1612 else if (xmlStrEqual(val, BAD_CAST "false"))
1613 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00001614 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001615 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
1616 "Attribute %s: the value %s is not boolean\n",
1617 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001618 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001619 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00001620}
1621
1622/************************************************************************
1623 * *
1624 * Shema extraction from an Infoset *
1625 * *
1626 ************************************************************************/
1627static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
1628 ctxt, xmlSchemaPtr schema,
1629 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001630static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
1631 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001632 xmlSchemaPtr schema,
1633 xmlNodePtr node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001634static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
1635 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00001636 xmlSchemaPtr schema,
1637 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001638 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00001639static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
1640 xmlSchemaPtr schema,
1641 xmlNodePtr node);
1642static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
1643 xmlSchemaPtr schema,
1644 xmlNodePtr node);
1645static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
1646 ctxt,
1647 xmlSchemaPtr schema,
1648 xmlNodePtr node);
1649static xmlSchemaAttributeGroupPtr
1650xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1651 xmlSchemaPtr schema, xmlNodePtr node);
1652static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
1653 xmlSchemaPtr schema,
1654 xmlNodePtr node);
1655static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
1656 xmlSchemaPtr schema,
1657 xmlNodePtr node);
1658static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001659xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1660 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001661
1662/**
1663 * xmlSchemaParseAttrDecls:
1664 * @ctxt: a schema validation context
1665 * @schema: the schema being built
1666 * @node: a subtree containing XML Schema informations
1667 * @type: the hosting type
1668 *
1669 * parse a XML schema attrDecls declaration corresponding to
1670 * <!ENTITY % attrDecls
1671 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
1672 */
1673static xmlNodePtr
1674xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1675 xmlNodePtr child, xmlSchemaTypePtr type)
1676{
1677 xmlSchemaAttributePtr lastattr, attr;
1678
1679 lastattr = NULL;
1680 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001681 (IS_SCHEMA(child, "attributeGroup"))) {
1682 attr = NULL;
1683 if (IS_SCHEMA(child, "attribute")) {
1684 attr = xmlSchemaParseAttribute(ctxt, schema, child);
1685 } else if (IS_SCHEMA(child, "attributeGroup")) {
1686 attr = (xmlSchemaAttributePtr)
1687 xmlSchemaParseAttributeGroup(ctxt, schema, child);
1688 }
1689 if (attr != NULL) {
1690 if (lastattr == NULL) {
1691 type->attributes = attr;
1692 lastattr = attr;
1693 } else {
1694 lastattr->next = attr;
1695 lastattr = attr;
1696 }
1697 }
1698 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001699 }
1700 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001701 attr = xmlSchemaParseAnyAttribute(ctxt, schema, child);
1702 if (attr != NULL) {
1703 if (lastattr == NULL) {
1704 type->attributes = attr;
1705 lastattr = attr;
1706 } else {
1707 lastattr->next = attr;
1708 lastattr = attr;
1709 }
1710 }
1711 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001712 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001713 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00001714}
1715
1716/**
1717 * xmlSchemaParseAnnotation:
1718 * @ctxt: a schema validation context
1719 * @schema: the schema being built
1720 * @node: a subtree containing XML Schema informations
1721 *
1722 * parse a XML schema Attrribute declaration
1723 * *WARNING* this interface is highly subject to change
1724 *
1725 * Returns -1 in case of error, 0 if the declaration is inproper and
1726 * 1 in case of success.
1727 */
1728static xmlSchemaAnnotPtr
1729xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1730 xmlNodePtr node)
1731{
1732 xmlSchemaAnnotPtr ret;
1733
1734 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1735 return (NULL);
1736 ret = xmlSchemaNewAnnot(ctxt, node);
1737
1738 return (ret);
1739}
1740
1741/**
1742 * xmlSchemaParseFacet:
1743 * @ctxt: a schema validation context
1744 * @schema: the schema being built
1745 * @node: a subtree containing XML Schema informations
1746 *
1747 * parse a XML schema Facet declaration
1748 * *WARNING* this interface is highly subject to change
1749 *
1750 * Returns the new type structure or NULL in case of error
1751 */
1752static xmlSchemaFacetPtr
1753xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001754 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001755{
1756 xmlSchemaFacetPtr facet;
1757 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001758 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00001759
1760 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1761 return (NULL);
1762
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001763 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001764 if (facet == NULL) {
1765 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
1766 return (NULL);
1767 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001768 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001769 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00001770 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001771 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
1772 "Facet %s has no value\n", node->name, NULL);
1773 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00001774 return (NULL);
1775 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001776 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001777 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001778 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001779 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001780 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001781 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001782 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001783 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001784 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001785 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001786 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001787 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001788 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001789 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001790 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001791 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001792 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001793 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001794 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001795 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001796 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001797 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
1798 } else if (IS_SCHEMA(node, "minLength")) {
1799 facet->type = XML_SCHEMA_FACET_MINLENGTH;
1800 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001801 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
1802 "Unknown facet type %s\n", node->name, NULL);
1803 xmlSchemaFreeFacet(facet);
1804 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001805 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001806 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00001807 facet->value = value;
1808 child = node->children;
1809
1810 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001811 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1812 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001813 }
1814 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001815 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
1816 "Facet %s has unexpected child content\n",
1817 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001818 }
1819 return (facet);
1820}
1821
1822/**
1823 * xmlSchemaParseAny:
1824 * @ctxt: a schema validation context
1825 * @schema: the schema being built
1826 * @node: a subtree containing XML Schema informations
1827 *
1828 * parse a XML schema Any declaration
1829 * *WARNING* this interface is highly subject to change
1830 *
1831 * Returns the new type structure or NULL in case of error
1832 */
1833static xmlSchemaTypePtr
1834xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1835 xmlNodePtr node)
1836{
1837 xmlSchemaTypePtr type;
1838 xmlNodePtr child = NULL;
1839 xmlChar name[30];
1840
1841 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1842 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001843 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001844 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001845 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001846 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001847 type->node = node;
1848 type->type = XML_SCHEMA_TYPE_ANY;
1849 child = node->children;
1850 type->minOccurs = xmlGetMinOccurs(ctxt, node);
1851 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
1852
1853 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001854 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001856 }
1857 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001858 xmlSchemaPErr2(ctxt, node, child,
1859 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
1860 "Sequence %s has unexpected content\n", type->name,
1861 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001862 }
1863
1864 return (type);
1865}
1866
1867/**
1868 * xmlSchemaParseNotation:
1869 * @ctxt: a schema validation context
1870 * @schema: the schema being built
1871 * @node: a subtree containing XML Schema informations
1872 *
1873 * parse a XML schema Notation declaration
1874 *
1875 * Returns the new structure or NULL in case of error
1876 */
1877static xmlSchemaNotationPtr
1878xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001879 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001880{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001881 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00001882 xmlSchemaNotationPtr ret;
1883 xmlNodePtr child = NULL;
1884
1885 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1886 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001887 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001888 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001889 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
1890 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001891 return (NULL);
1892 }
1893 ret = xmlSchemaAddNotation(ctxt, schema, name);
1894 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001895 return (NULL);
1896 }
1897 child = node->children;
1898 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001899 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1900 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001901 }
1902 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001903 xmlSchemaPErr2(ctxt, node, child,
1904 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
1905 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001906 }
1907
1908 return (ret);
1909}
1910
1911/**
1912 * xmlSchemaParseAnyAttribute:
1913 * @ctxt: a schema validation context
1914 * @schema: the schema being built
1915 * @node: a subtree containing XML Schema informations
1916 *
1917 * parse a XML schema AnyAttrribute declaration
1918 * *WARNING* this interface is highly subject to change
1919 *
1920 * Returns an attribute def structure or NULL
1921 */
1922static xmlSchemaAttributePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001923xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
1924 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00001925{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001926 const xmlChar *processContents;
Daniel Veillard4255d502002-04-16 15:50:10 +00001927 xmlSchemaAttributePtr ret;
1928 xmlNodePtr child = NULL;
1929 char name[100];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001930 const xmlChar *local, *ns;
1931
Daniel Veillard4255d502002-04-16 15:50:10 +00001932
1933 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1934 return (NULL);
1935
1936 snprintf(name, 99, "anyattr %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001937 local = xmlSchemaGetNamespace(ctxt, schema, node, BAD_CAST "anyattr", &ns);
1938 ret = xmlSchemaAddAttribute(ctxt, schema, BAD_CAST name, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00001939 if (ret == NULL) {
1940 return (NULL);
1941 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001942 ret->id = xmlSchemaGetProp(ctxt, node, "id");
1943 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001944 if ((processContents == NULL)
1945 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
1946 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
1947 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
1948 ret->occurs = XML_SCHEMAS_ANYATTR_SKIP;
1949 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
1950 ret->occurs = XML_SCHEMAS_ANYATTR_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00001951 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001952 xmlSchemaPErr2(ctxt, node, child,
1953 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
1954 "anyAttribute has unexpected content for processContents: %s\n",
1955 processContents, NULL);
1956 ret->occurs = XML_SCHEMAS_ANYATTR_STRICT;
Daniel Veillard4255d502002-04-16 15:50:10 +00001957 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001958
1959 child = node->children;
1960 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001961 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
1962 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001963 }
1964 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001965 xmlSchemaPErr2(ctxt, node, child,
1966 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
1967 "anyAttribute %s has unexpected content\n",
1968 (const xmlChar *) name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001969 }
1970
1971 return (ret);
1972}
1973
1974
1975/**
1976 * xmlSchemaParseAttribute:
1977 * @ctxt: a schema validation context
1978 * @schema: the schema being built
1979 * @node: a subtree containing XML Schema informations
1980 *
1981 * parse a XML schema Attrribute declaration
1982 * *WARNING* this interface is highly subject to change
1983 *
1984 * Returns -1 in case of error, 0 if the declaration is inproper and
1985 * 1 in case of success.
1986 */
1987static xmlSchemaAttributePtr
1988xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1989 xmlNodePtr node)
1990{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001991 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00001992 xmlSchemaAttributePtr ret;
1993 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001994 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001995
1996 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
1997 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001998 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00001999 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002000
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002001 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2002 if (ref == NULL) {
2003 xmlSchemaPErr2(ctxt, node, child,
2004 XML_SCHEMAP_ATTR_NONAME_NOREF,
2005 "Attribute has no name nor ref\n", NULL, NULL);
2006 return (NULL);
2007 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002008 if (refNs == NULL)
2009 refNs = schema->targetNamespace;
2010 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2011 name = (const xmlChar *) buf;
2012 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
2013 } else {
2014 const xmlChar *local, *ns;
2015
2016 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2017 ret = xmlSchemaAddAttribute(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002018 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002019 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002020 return (NULL);
2021 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002022 ret->ref = ref;
2023 ret->refNs = refNs;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002024 if ((ret->targetNamespace != NULL) &&
2025 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2026 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2027 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
Daniel Veillard4255d502002-04-16 15:50:10 +00002028 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002029 if ((ret->typeName != NULL) && (ret->typeNs == NULL))
2030 ret->typeNs = schema->targetNamespace;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002031 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002032 child = node->children;
2033 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002034 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2035 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002036 }
2037 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002038 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
2039 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002040 }
2041 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002042 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2043 "attribute %s has unexpected content\n", name,
2044 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002045 }
2046
2047 return (ret);
2048}
2049
2050/**
2051 * xmlSchemaParseAttributeGroup:
2052 * @ctxt: a schema validation context
2053 * @schema: the schema being built
2054 * @node: a subtree containing XML Schema informations
2055 *
2056 * parse a XML schema Attribute Group declaration
2057 * *WARNING* this interface is highly subject to change
2058 *
2059 * Returns the attribute group or NULL in case of error.
2060 */
2061static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002062xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2063 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002064{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002065 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002066 xmlSchemaAttributeGroupPtr ret;
2067 xmlSchemaAttributePtr last = NULL, attr;
2068 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002069 const xmlChar *oldcontainer;
2070 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002071
2072 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2073 return (NULL);
2074 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002075 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002076 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002077
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002078 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2079 if (ref == NULL) {
2080 xmlSchemaPErr2(ctxt, node, child,
2081 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
2082 "AttributeGroup has no name nor ref\n", NULL,
2083 NULL);
2084 return (NULL);
2085 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002086 if (refNs == NULL)
2087 refNs = schema->targetNamespace;
2088 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
2089 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002090 if (name == NULL) {
2091 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
2092 return (NULL);
2093 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002094 }
2095 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
2096 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002097 return (NULL);
2098 }
2099 ret->ref = ref;
2100 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00002101 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002102 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002103 child = node->children;
2104 ctxt->container = name;
2105 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002106 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2107 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002108 }
2109 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002110 (IS_SCHEMA(child, "attributeGroup"))) {
2111 attr = NULL;
2112 if (IS_SCHEMA(child, "attribute")) {
2113 attr = xmlSchemaParseAttribute(ctxt, schema, child);
2114 } else if (IS_SCHEMA(child, "attributeGroup")) {
2115 attr = (xmlSchemaAttributePtr)
2116 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2117 }
2118 if (attr != NULL) {
2119 if (last == NULL) {
2120 ret->attributes = attr;
2121 last = attr;
2122 } else {
2123 last->next = attr;
2124 last = attr;
2125 }
2126 }
2127 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002128 }
2129 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002130 TODO
2131 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002132 }
2133 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002134 xmlSchemaPErr2(ctxt, node, child,
2135 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
2136 "attribute group %s has unexpected content\n", name,
2137 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002138 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002139 ctxt->container = oldcontainer;
2140 return (ret);
2141}
2142
2143/**
2144 * xmlSchemaParseElement:
2145 * @ctxt: a schema validation context
2146 * @schema: the schema being built
2147 * @node: a subtree containing XML Schema informations
2148 *
2149 * parse a XML schema Element declaration
2150 * *WARNING* this interface is highly subject to change
2151 *
2152 * Returns -1 in case of error, 0 if the declaration is inproper and
2153 * 1 in case of success.
2154 */
2155static xmlSchemaElementPtr
2156xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2157 xmlNodePtr node, int toplevel)
2158{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002159 const xmlChar *name, *fixed;
2160 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002161 xmlSchemaElementPtr ret;
2162 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002163 const xmlChar *oldcontainer;
2164 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002165
2166 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2167 return (NULL);
2168 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002169 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002170 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002171
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002172 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2173 if (ref == NULL) {
2174 xmlSchemaPErr2(ctxt, node, child,
2175 XML_SCHEMAP_ELEM_NONAME_NOREF,
2176 "Element has no name nor ref\n", NULL, NULL);
2177 return (NULL);
2178 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002179 if (refNs == NULL)
2180 refNs = schema->targetNamespace;
2181 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
2182 name = (const xmlChar *) buf;
2183 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
2184 } else {
2185 const xmlChar *local, *ns;
2186
2187 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2188 ret = xmlSchemaAddElement(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002189 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002190 if (ret != NULL)
2191 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002192 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002193 return (NULL);
2194 }
2195 ret->type = XML_SCHEMA_TYPE_ELEMENT;
2196 ret->ref = ref;
2197 ret->refNs = refNs;
2198 if (ref != NULL)
2199 ret->flags |= XML_SCHEMAS_ELEM_REF;
2200 if (toplevel)
2201 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
2202 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
2203 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2204 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
2205 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
2206 ctxt->container = name;
2207
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002208 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002209 ret->namedType =
2210 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002211 if ((ret->namedType != NULL) && (ret->namedTypeNs == NULL))
2212 ret->namedTypeNs = schema->targetNamespace;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002213 ret->substGroup =
2214 xmlGetQNameProp(ctxt, node, "substitutionGroup",
2215 &(ret->substGroupNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002216 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
2218 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002219
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002220 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00002221 if ((ret->value != NULL) && (fixed != NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002222 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
2223 "Element %s has both default and fixed\n",
2224 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002225 } else if (fixed != NULL) {
2226 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002227 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00002228 }
2229
2230 child = node->children;
2231 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002232 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2233 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002234 }
2235 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002236 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002237 child = child->next;
2238 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002239 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002240 child = child->next;
2241 }
2242 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
2244 TODO child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002245 }
2246 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002247 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
2248 "element %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002249 }
2250
2251 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00002252 return (ret);
2253}
2254
2255/**
2256 * xmlSchemaParseUnion:
2257 * @ctxt: a schema validation context
2258 * @schema: the schema being built
2259 * @node: a subtree containing XML Schema informations
2260 *
2261 * parse a XML schema Union definition
2262 * *WARNING* this interface is highly subject to change
2263 *
2264 * Returns -1 in case of error, 0 if the declaration is inproper and
2265 * 1 in case of success.
2266 */
2267static xmlSchemaTypePtr
2268xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002269 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002270{
2271 xmlSchemaTypePtr type, subtype, last = NULL;
2272 xmlNodePtr child = NULL;
2273 xmlChar name[30];
2274
2275 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2276 return (NULL);
2277
2278
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002279 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002280 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002281 if (type == NULL)
2282 return (NULL);
2283 type->node = node;
2284 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002285 type->id = xmlSchemaGetProp(ctxt, node, "id");
2286 type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00002287
2288 child = node->children;
2289 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002290 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2291 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002292 }
2293 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002294 subtype = (xmlSchemaTypePtr)
2295 xmlSchemaParseSimpleType(ctxt, schema, child);
2296 if (subtype != NULL) {
2297 if (last == NULL) {
2298 type->subtypes = subtype;
2299 last = subtype;
2300 } else {
2301 last->next = subtype;
2302 last = subtype;
2303 }
2304 last->next = NULL;
2305 }
2306 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002307 }
2308 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002309 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
2310 "Union %s has unexpected content\n", type->name,
2311 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002312 }
2313 return (type);
2314}
2315
2316/**
2317 * xmlSchemaParseList:
2318 * @ctxt: a schema validation context
2319 * @schema: the schema being built
2320 * @node: a subtree containing XML Schema informations
2321 *
2322 * parse a XML schema List definition
2323 * *WARNING* this interface is highly subject to change
2324 *
2325 * Returns -1 in case of error, 0 if the declaration is inproper and
2326 * 1 in case of success.
2327 */
2328static xmlSchemaTypePtr
2329xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002330 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002331{
2332 xmlSchemaTypePtr type, subtype;
2333 xmlNodePtr child = NULL;
2334 xmlChar name[30];
2335
2336 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2337 return (NULL);
2338
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002339 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002340 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002341 if (type == NULL)
2342 return (NULL);
2343 type->node = node;
2344 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002345 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002346 type->ref = xmlGetQNameProp(ctxt, node, "ref", &(type->refNs));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002347 if ((type->ref != NULL) && (type->refNs == NULL))
2348 type->refNs = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00002349
2350 child = node->children;
2351 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002352 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2353 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002354 }
2355 subtype = NULL;
2356 if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002357 subtype = (xmlSchemaTypePtr)
2358 xmlSchemaParseSimpleType(ctxt, schema, child);
2359 child = child->next;
2360 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002361 }
2362 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002363 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
2364 "List %s has unexpected content\n", type->name,
2365 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002366 }
2367 return (type);
2368}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002369
Daniel Veillard4255d502002-04-16 15:50:10 +00002370/**
2371 * xmlSchemaParseSimpleType:
2372 * @ctxt: a schema validation context
2373 * @schema: the schema being built
2374 * @node: a subtree containing XML Schema informations
2375 *
2376 * parse a XML schema Simple Type definition
2377 * *WARNING* this interface is highly subject to change
2378 *
2379 * Returns -1 in case of error, 0 if the declaration is inproper and
2380 * 1 in case of success.
2381 */
2382static xmlSchemaTypePtr
2383xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2384 xmlNodePtr node)
2385{
2386 xmlSchemaTypePtr type, subtype;
2387 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002388 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002389
2390 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2391 return (NULL);
2392
2393
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002394 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002395 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002396 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002397
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002398 snprintf(buf, 99, "simpletype %d", ctxt->counter++ + 1);
2399 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
2400 } else {
2401 const xmlChar *local, *ns;
2402
2403 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
2404 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00002405 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002406 if (type == NULL)
2407 return (NULL);
2408 type->node = node;
2409 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002410 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002411
2412 child = node->children;
2413 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002414 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2415 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002416 }
2417 subtype = NULL;
2418 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002419 subtype = (xmlSchemaTypePtr)
2420 xmlSchemaParseRestriction(ctxt, schema, child, 1);
2421 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002422 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002423 subtype = (xmlSchemaTypePtr)
2424 xmlSchemaParseList(ctxt, schema, child);
2425 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002426 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002427 subtype = (xmlSchemaTypePtr)
2428 xmlSchemaParseUnion(ctxt, schema, child);
2429 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002430 }
2431 type->subtypes = subtype;
2432 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002433 xmlSchemaPErr2(ctxt, node, child,
2434 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,
2435 "SimpleType %s has unexpected content\n",
2436 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002437 }
2438
2439 return (type);
2440}
2441
2442
2443/**
2444 * xmlSchemaParseGroup:
2445 * @ctxt: a schema validation context
2446 * @schema: the schema being built
2447 * @node: a subtree containing XML Schema informations
2448 *
2449 * parse a XML schema Group definition
2450 * *WARNING* this interface is highly subject to change
2451 *
2452 * Returns -1 in case of error, 0 if the declaration is inproper and
2453 * 1 in case of success.
2454 */
2455static xmlSchemaTypePtr
2456xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002457 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002458{
2459 xmlSchemaTypePtr type, subtype;
2460 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002461 const xmlChar *name;
2462 const xmlChar *ref = NULL, *refNs = NULL;
2463 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002464
2465 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2466 return (NULL);
2467
2468
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002469 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002470 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002471
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002472 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
2473 if (ref == NULL) {
2474 xmlSchemaPErr2(ctxt, node, child,
2475 XML_SCHEMAP_GROUP_NONAME_NOREF,
2476 "Group has no name nor ref\n", NULL, NULL);
2477 return (NULL);
2478 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002479 if (refNs == NULL)
2480 refNs = schema->targetNamespace;
2481 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
2482 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00002483 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002484 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002485 if (type == NULL)
2486 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00002487
Daniel Veillard4255d502002-04-16 15:50:10 +00002488 type->node = node;
2489 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002490 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002491 type->ref = ref;
2492 type->refNs = refNs;
2493 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2494 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2495
2496 child = node->children;
2497 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002498 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2499 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002500 }
2501 subtype = NULL;
2502 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002503 subtype = (xmlSchemaTypePtr)
2504 xmlSchemaParseAll(ctxt, schema, child);
2505 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002506 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002507 subtype = xmlSchemaParseChoice(ctxt, schema, child);
2508 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002509 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002510 subtype = (xmlSchemaTypePtr)
2511 xmlSchemaParseSequence(ctxt, schema, child);
2512 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002513 }
2514 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002515 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00002516 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002517 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
2518 "Group %s has unexpected content\n", type->name,
2519 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002520 }
2521
2522 return (type);
2523}
2524
2525/**
2526 * xmlSchemaParseAll:
2527 * @ctxt: a schema validation context
2528 * @schema: the schema being built
2529 * @node: a subtree containing XML Schema informations
2530 *
2531 * parse a XML schema All definition
2532 * *WARNING* this interface is highly subject to change
2533 *
2534 * Returns -1 in case of error, 0 if the declaration is inproper and
2535 * 1 in case of success.
2536 */
2537static xmlSchemaTypePtr
2538xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002539 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002540{
2541 xmlSchemaTypePtr type, subtype, last = NULL;
2542 xmlNodePtr child = NULL;
2543 xmlChar name[30];
2544
2545 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2546 return (NULL);
2547
2548
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002549 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002550 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002551 if (type == NULL)
2552 return (NULL);
2553 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00002554 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002555 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002556 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002557 if (type->minOccurs > 1)
2558 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2559 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002560 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00002561 if (type->maxOccurs > 1)
2562 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2563 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002564
2565 child = node->children;
2566 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002567 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2568 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002569 }
2570 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002571 subtype = (xmlSchemaTypePtr)
2572 xmlSchemaParseElement(ctxt, schema, child, 0);
2573 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00002574 if (subtype->minOccurs > 1)
2575 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
2576 "invalid value for minOccurs (must be 0 or 1)\n",
2577 NULL, NULL);
2578 if (subtype->maxOccurs > 1)
2579 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
2580 "invalid value for maxOccurs (must be 0 or 1)\n",
2581 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002582 if (last == NULL) {
2583 type->subtypes = subtype;
2584 last = subtype;
2585 } else {
2586 last->next = subtype;
2587 last = subtype;
2588 }
2589 last->next = NULL;
2590 }
2591 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002592 }
2593 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002594 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
2595 "All %s has unexpected content\n", type->name,
2596 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002597 }
2598
2599 return (type);
2600}
2601
2602/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002603 * xmlSchemaImportSchema
2604 *
2605 * @ctxt: a schema validation context
2606 * @schemaLocation: an URI defining where to find the imported schema
2607 *
2608 * import a XML schema
2609 * *WARNING* this interface is highly subject to change
2610 *
2611 * Returns -1 in case of error and 1 in case of success.
2612 */
2613static xmlSchemaImportPtr
2614xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
2615 const xmlChar *schemaLocation)
2616{
2617 xmlSchemaImportPtr import;
2618 xmlSchemaParserCtxtPtr newctxt;
2619
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002620 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00002621 if (newctxt == NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002622 xmlSchemaPErrMemory(ctxt, "allocating schama parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00002623 NULL);
2624 return (NULL);
2625 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002626 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
2627 /* Keep the same dictionnary for parsing, really */
2628 xmlDictReference(ctxt->dict);
2629 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002630 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002631 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
2632
Daniel Veillard1d913862003-11-21 00:28:39 +00002633 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
2634 ctxt->userData);
2635
2636 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
2637 if (import == NULL) {
2638 xmlSchemaPErrMemory(NULL, "allocating imported schema",
2639 NULL);
2640 xmlSchemaFreeParserCtxt(newctxt);
2641 return (NULL);
2642 }
2643
2644 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002645 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00002646 import->schema = xmlSchemaParse(newctxt);
2647
2648 if (import->schema == NULL) {
2649 /* FIXME use another error enum here ? */
2650 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
2651 "failed to import schema at location %s\n",
2652 schemaLocation, NULL);
2653
2654 xmlSchemaFreeParserCtxt(newctxt);
2655 if (import->schemaLocation != NULL)
2656 xmlFree((xmlChar *)import->schemaLocation);
2657 xmlFree(import);
2658 return NULL;
2659 }
2660
2661 xmlSchemaFreeParserCtxt(newctxt);
2662 return import;
2663}
2664
2665
2666/**
Daniel Veillard5a872412002-05-22 06:40:27 +00002667 * xmlSchemaParseImport:
2668 * @ctxt: a schema validation context
2669 * @schema: the schema being built
2670 * @node: a subtree containing XML Schema informations
2671 *
2672 * parse a XML schema Import definition
2673 * *WARNING* this interface is highly subject to change
2674 *
2675 * Returns -1 in case of error, 0 if the declaration is inproper and
2676 * 1 in case of success.
2677 */
2678static int
2679xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002680 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00002681{
2682 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00002683 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002684 const xmlChar *namespace;
2685 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00002686 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00002687 xmlURIPtr check;
2688
Daniel Veillard1d913862003-11-21 00:28:39 +00002689
Daniel Veillard5a872412002-05-22 06:40:27 +00002690 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2691 return (-1);
2692
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002693 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00002694 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002695 check = xmlParseURI((const char *) namespace);
2696 if (check == NULL) {
2697 xmlSchemaPErr2(ctxt, node, child,
2698 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
2699 "Import namespace attribute is not an URI: %s\n",
2700 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002701 return (-1);
2702 } else {
2703 xmlFreeURI(check);
2704 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002705 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002706 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00002707 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002708 xmlChar *base = NULL;
2709 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002710 check = xmlParseURI((const char *) schemaLocation);
2711 if (check == NULL) {
2712 xmlSchemaPErr2(ctxt, node, child,
2713 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
2714 "Import schemaLocation attribute is not an URI: %s\n",
2715 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002716 return (-1);
2717 } else {
2718 xmlFreeURI(check);
2719 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002720 base = xmlNodeGetBase(node->doc, node);
2721 if (base == NULL) {
2722 URI = xmlBuildURI(schemaLocation, node->doc->URL);
2723 } else {
2724 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002725 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00002726 }
Daniel Veillard1d913862003-11-21 00:28:39 +00002727 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002728 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
2729 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00002730 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002731 }
2732 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002733 schema->schemasImports = xmlHashCreate(10);
2734 if (schema->schemasImports == NULL) {
2735 xmlSchemaPErr2(ctxt, node, child,
2736 XML_SCHEMAP_FAILED_BUILD_IMPORT,
2737 "Internal: failed to build import table\n",
2738 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002739 return (-1);
2740 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002741 }
2742 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002743 import = xmlHashLookup(schema->schemasImports,
2744 XML_SCHEMAS_DEFAULT_NAMESPACE);
2745 if (import != NULL)
2746 previous = import->schemaLocation;
2747 else
2748 previous = NULL;
2749
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002750 if (schemaLocation != NULL) {
2751 if (previous != NULL) {
2752 if (!xmlStrEqual(schemaLocation, previous)) {
2753 xmlSchemaPErr2(ctxt, node, child,
2754 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2755 "Redefining import for default namespace with a different URI: %s\n",
2756 schemaLocation, NULL);
2757 }
2758 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002759 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2760 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002761 return (-1);
2762 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002763 xmlHashAddEntry(schema->schemasImports,
2764 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00002765 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002766 }
2767 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002768 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002769 import = xmlHashLookup(schema->schemasImports, namespace);
2770 if (import != NULL)
2771 previous = import->schemaLocation;
2772 else
2773 previous = NULL;
2774
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002775 if (schemaLocation != NULL) {
2776 if (previous != NULL) {
2777 if (!xmlStrEqual(schemaLocation, previous)) {
2778 xmlSchemaPErr2(ctxt, node, child,
2779 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
2780 "Redefining import for namespace %s with a different URI: %s\n",
2781 namespace, schemaLocation);
2782 }
2783 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00002784 import = xmlSchemaImportSchema(ctxt, schemaLocation);
2785 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002786 return (-1);
2787 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002788 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00002789 namespace, import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002790 }
2791 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002792 }
Daniel Veillard5a872412002-05-22 06:40:27 +00002793
2794 child = node->children;
2795 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002796 /*
2797 * the annotations here are simply discarded ...
2798 */
2799 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00002800 }
2801 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002802 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
2803 "Import has unexpected content\n", NULL, NULL);
2804 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002805 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002806 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00002807}
2808
2809/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002810 * xmlSchemaCleanupDoc:
2811 * @ctxt: a schema validation context
2812 * @node: the root of the document.
2813 *
2814 * removes unwanted nodes in a schemas document tree
2815 */
2816static void
2817xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
2818{
2819 xmlNodePtr delete, cur;
2820
2821 if ((ctxt == NULL) || (root == NULL)) return;
2822
2823 /*
2824 * Remove all the blank text nodes
2825 */
2826 delete = NULL;
2827 cur = root;
2828 while (cur != NULL) {
2829 if (delete != NULL) {
2830 xmlUnlinkNode(delete);
2831 xmlFreeNode(delete);
2832 delete = NULL;
2833 }
2834 if (cur->type == XML_TEXT_NODE) {
2835 if (IS_BLANK_NODE(cur)) {
2836 if (xmlNodeGetSpacePreserve(cur) != 1) {
2837 delete = cur;
2838 }
2839 }
2840 } else if ((cur->type != XML_ELEMENT_NODE) &&
2841 (cur->type != XML_CDATA_SECTION_NODE)) {
2842 delete = cur;
2843 goto skip_children;
2844 }
2845
2846 /*
2847 * Skip to next node
2848 */
2849 if (cur->children != NULL) {
2850 if ((cur->children->type != XML_ENTITY_DECL) &&
2851 (cur->children->type != XML_ENTITY_REF_NODE) &&
2852 (cur->children->type != XML_ENTITY_NODE)) {
2853 cur = cur->children;
2854 continue;
2855 }
2856 }
2857 skip_children:
2858 if (cur->next != NULL) {
2859 cur = cur->next;
2860 continue;
2861 }
2862
2863 do {
2864 cur = cur->parent;
2865 if (cur == NULL)
2866 break;
2867 if (cur == root) {
2868 cur = NULL;
2869 break;
2870 }
2871 if (cur->next != NULL) {
2872 cur = cur->next;
2873 break;
2874 }
2875 } while (cur != NULL);
2876 }
2877 if (delete != NULL) {
2878 xmlUnlinkNode(delete);
2879 xmlFreeNode(delete);
2880 delete = NULL;
2881 }
2882}
2883
2884/**
2885 * xmlSchemaParseSchemaTopLevel:
2886 * @ctxt: a schema validation context
2887 * @schema: the schemas
2888 * @nodes: the list of top level nodes
2889 *
2890 * Returns the internal XML Schema structure built from the resource or
2891 * NULL in case of error
2892 */
2893static void
2894xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
2895 xmlSchemaPtr schema, xmlNodePtr nodes)
2896{
2897 xmlNodePtr child;
2898 xmlSchemaAnnotPtr annot;
2899
2900 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
2901 return;
2902
2903 child = nodes;
2904 while ((IS_SCHEMA(child, "include")) ||
2905 (IS_SCHEMA(child, "import")) ||
2906 (IS_SCHEMA(child, "redefine")) ||
2907 (IS_SCHEMA(child, "annotation"))) {
2908 if (IS_SCHEMA(child, "annotation")) {
2909 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2910 if (schema->annot == NULL)
2911 schema->annot = annot;
2912 else
2913 xmlSchemaFreeAnnot(annot);
2914 } else if (IS_SCHEMA(child, "import")) {
2915 xmlSchemaParseImport(ctxt, schema, child);
2916 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002917 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002918 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002919 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002920 } else if (IS_SCHEMA(child, "redefine")) {
2921 TODO
2922 }
2923 child = child->next;
2924 }
2925 while (child != NULL) {
2926 if (IS_SCHEMA(child, "complexType")) {
2927 xmlSchemaParseComplexType(ctxt, schema, child);
2928 child = child->next;
2929 } else if (IS_SCHEMA(child, "simpleType")) {
2930 xmlSchemaParseSimpleType(ctxt, schema, child);
2931 child = child->next;
2932 } else if (IS_SCHEMA(child, "element")) {
2933 xmlSchemaParseElement(ctxt, schema, child, 1);
2934 child = child->next;
2935 } else if (IS_SCHEMA(child, "attribute")) {
2936 xmlSchemaParseAttribute(ctxt, schema, child);
2937 child = child->next;
2938 } else if (IS_SCHEMA(child, "attributeGroup")) {
2939 xmlSchemaParseAttributeGroup(ctxt, schema, child);
2940 child = child->next;
2941 } else if (IS_SCHEMA(child, "group")) {
2942 xmlSchemaParseGroup(ctxt, schema, child);
2943 child = child->next;
2944 } else if (IS_SCHEMA(child, "notation")) {
2945 xmlSchemaParseNotation(ctxt, schema, child);
2946 child = child->next;
2947 } else {
2948 xmlSchemaPErr2(ctxt, NULL, child,
2949 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
2950 "Schemas: unexpected element %s here \n",
2951 child->name, NULL);
2952 child = child->next;
2953 }
2954 while (IS_SCHEMA(child, "annotation")) {
2955 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2956 if (schema->annot == NULL)
2957 schema->annot = annot;
2958 else
2959 xmlSchemaFreeAnnot(annot);
2960 child = child->next;
2961 }
2962 }
2963}
2964
2965/**
2966 * xmlSchemaParseInclude:
2967 * @ctxt: a schema validation context
2968 * @schema: the schema being built
2969 * @node: a subtree containing XML Schema informations
2970 *
2971 * parse a XML schema Include definition
2972 *
2973 * Returns -1 in case of error, 0 if the declaration is inproper and
2974 * 1 in case of success.
2975 */
2976static int
2977xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2978 xmlNodePtr node)
2979{
2980 xmlNodePtr child = NULL;
2981 const xmlChar *schemaLocation;
2982 xmlURIPtr check;
2983 xmlDocPtr doc;
2984 xmlNodePtr root;
2985 xmlSchemaIncludePtr include;
2986
2987
2988 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2989 return (-1);
2990
2991 /*
2992 * Preliminary step, extract the URI-Reference for the include and
2993 * make an URI from the base.
2994 */
2995 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
2996 if (schemaLocation != NULL) {
2997 xmlChar *base = NULL;
2998 xmlChar *URI = NULL;
2999 check = xmlParseURI((const char *) schemaLocation);
3000 if (check == NULL) {
3001 xmlSchemaPErr2(ctxt, node, child,
3002 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
3003 "Include schemaLocation attribute is not an URI: %s\n",
3004 schemaLocation, NULL);
3005 return (-1);
3006 } else {
3007 xmlFreeURI(check);
3008 }
3009 base = xmlNodeGetBase(node->doc, node);
3010 if (base == NULL) {
3011 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3012 } else {
3013 URI = xmlBuildURI(schemaLocation, base);
3014 xmlFree(base);
3015 }
3016 if (URI != NULL) {
3017 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3018 xmlFree(URI);
3019 }
3020 } else {
3021 xmlSchemaPErr2(ctxt, node, child,
3022 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
3023 "Include schemaLocation attribute missing\n",
3024 NULL, NULL);
3025 return (-1);
3026 }
3027
3028 child = node->children;
3029 while (IS_SCHEMA(child, "annotation")) {
3030 /*
3031 * the annotations here are simply discarded ...
3032 */
3033 child = child->next;
3034 }
3035 if (child != NULL) {
3036 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
3037 "Include has unexpected content\n", NULL, NULL);
3038 return (-1);
3039 }
3040
3041 /*
3042 * First step is to parse the input document into an DOM/Infoset
3043 */
3044 doc = xmlReadFile((const char *) schemaLocation, NULL,
3045 SCHEMAS_PARSE_OPTIONS);
3046 if (doc == NULL) {
3047 xmlSchemaPErr(ctxt, NULL,
3048 XML_SCHEMAP_FAILED_LOAD,
3049 "xmlSchemaParse: could not load %s\n",
3050 ctxt->URL, NULL);
3051 return(-1);
3052 }
3053
3054 /*
3055 * Then extract the root of the schema
3056 */
3057 root = xmlDocGetRootElement(doc);
3058 if (root == NULL) {
3059 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3060 XML_SCHEMAP_NOROOT,
3061 "schemas %s has no root", schemaLocation, NULL);
3062 xmlFreeDoc(doc);
3063 return (-1);
3064 }
3065
3066 /*
3067 * Remove all the blank text nodes
3068 */
3069 xmlSchemaCleanupDoc(ctxt, root);
3070
3071 /*
3072 * Check the schemas top level element
3073 */
3074 if (!IS_SCHEMA(root, "schema")) {
3075 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3076 XML_SCHEMAP_NOT_SCHEMA,
3077 "File %s is not a schemas", schemaLocation, NULL);
3078 xmlFreeDoc(doc);
3079 return (-1);
3080 }
3081
3082 /*
3083 * register the include
3084 */
3085 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
3086 if (include == NULL) {
3087 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
3088 xmlFreeDoc(doc);
3089 return (-1);
3090 }
3091
3092 memset(include, 0, sizeof(xmlSchemaInclude));
3093 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
3094 include->doc = doc;
3095 include->next = schema->includes;
3096 schema->includes = include;
3097
3098
3099 /*
3100 * parse the declarations in the included file like if they
3101 * were in the original file.
3102 */
3103 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
3104
3105 return (1);
3106}
3107
3108/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003109 * xmlSchemaParseChoice:
3110 * @ctxt: a schema validation context
3111 * @schema: the schema being built
3112 * @node: a subtree containing XML Schema informations
3113 *
3114 * parse a XML schema Choice definition
3115 * *WARNING* this interface is highly subject to change
3116 *
3117 * Returns -1 in case of error, 0 if the declaration is inproper and
3118 * 1 in case of success.
3119 */
3120static xmlSchemaTypePtr
3121xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003122 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003123{
3124 xmlSchemaTypePtr type, subtype, last = NULL;
3125 xmlNodePtr child = NULL;
3126 xmlChar name[30];
3127
3128 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3129 return (NULL);
3130
3131
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003132 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003133 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003134 if (type == NULL)
3135 return (NULL);
3136 type->node = node;
3137 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003138 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003139 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3140 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3141
3142 child = node->children;
3143 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003144 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3145 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003146 }
3147 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003148 (IS_SCHEMA(child, "group")) ||
3149 (IS_SCHEMA(child, "any")) ||
3150 (IS_SCHEMA(child, "choice")) ||
3151 (IS_SCHEMA(child, "sequence"))) {
3152 subtype = NULL;
3153 if (IS_SCHEMA(child, "element")) {
3154 subtype = (xmlSchemaTypePtr)
3155 xmlSchemaParseElement(ctxt, schema, child, 0);
3156 } else if (IS_SCHEMA(child, "group")) {
3157 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3158 } else if (IS_SCHEMA(child, "any")) {
3159 subtype = xmlSchemaParseAny(ctxt, schema, child);
3160 } else if (IS_SCHEMA(child, "sequence")) {
3161 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3162 } else if (IS_SCHEMA(child, "choice")) {
3163 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3164 }
3165 if (subtype != NULL) {
3166 if (last == NULL) {
3167 type->subtypes = subtype;
3168 last = subtype;
3169 } else {
3170 last->next = subtype;
3171 last = subtype;
3172 }
3173 last->next = NULL;
3174 }
3175 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003176 }
3177 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003178 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
3179 "Choice %s has unexpected content\n", type->name,
3180 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003181 }
3182
3183 return (type);
3184}
3185
3186/**
3187 * xmlSchemaParseSequence:
3188 * @ctxt: a schema validation context
3189 * @schema: the schema being built
3190 * @node: a subtree containing XML Schema informations
3191 *
3192 * parse a XML schema Sequence definition
3193 * *WARNING* this interface is highly subject to change
3194 *
3195 * Returns -1 in case of error, 0 if the declaration is inproper and
3196 * 1 in case of success.
3197 */
3198static xmlSchemaTypePtr
3199xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003200 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003201{
3202 xmlSchemaTypePtr type, subtype, last = NULL;
3203 xmlNodePtr child = NULL;
3204 xmlChar name[30];
3205
3206 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3207 return (NULL);
3208
3209
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003210 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003211 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003212 if (type == NULL)
3213 return (NULL);
3214 type->node = node;
3215 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003216 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003217 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3218 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3219
3220 child = node->children;
3221 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003222 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3223 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003224 }
3225 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003226 (IS_SCHEMA(child, "group")) ||
3227 (IS_SCHEMA(child, "any")) ||
3228 (IS_SCHEMA(child, "choice")) ||
3229 (IS_SCHEMA(child, "sequence"))) {
3230 subtype = NULL;
3231 if (IS_SCHEMA(child, "element")) {
3232 subtype = (xmlSchemaTypePtr)
3233 xmlSchemaParseElement(ctxt, schema, child, 0);
3234 } else if (IS_SCHEMA(child, "group")) {
3235 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3236 } else if (IS_SCHEMA(child, "any")) {
3237 subtype = xmlSchemaParseAny(ctxt, schema, child);
3238 } else if (IS_SCHEMA(child, "choice")) {
3239 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3240 } else if (IS_SCHEMA(child, "sequence")) {
3241 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3242 }
3243 if (subtype != NULL) {
3244 if (last == NULL) {
3245 type->subtypes = subtype;
3246 last = subtype;
3247 } else {
3248 last->next = subtype;
3249 last = subtype;
3250 }
3251 last->next = NULL;
3252 }
3253 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003254 }
3255 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003256 xmlSchemaPErr2(ctxt, node, child,
3257 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
3258 "Sequence %s has unexpected content\n", type->name,
3259 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 }
3261
3262 return (type);
3263}
3264
3265/**
3266 * xmlSchemaParseRestriction:
3267 * @ctxt: a schema validation context
3268 * @schema: the schema being built
3269 * @node: a subtree containing XML Schema informations
3270 * @simple: is that part of a simple type.
3271 *
3272 * parse a XML schema Restriction definition
3273 * *WARNING* this interface is highly subject to change
3274 *
3275 * Returns the type definition or NULL in case of error
3276 */
3277static xmlSchemaTypePtr
3278xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3279 xmlNodePtr node, int simple)
3280{
3281 xmlSchemaTypePtr type, subtype;
3282 xmlSchemaFacetPtr facet, lastfacet = NULL;
3283 xmlNodePtr child = NULL;
3284 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003285 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003286
3287 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3288 return (NULL);
3289
3290 oldcontainer = ctxt->container;
3291
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003292 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003293 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003294 if (type == NULL)
3295 return (NULL);
3296 type->node = node;
3297 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003298 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003299 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3300 if ((!simple) && (type->base == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003301 xmlSchemaPErr2(ctxt, node, child,
3302 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
3303 "Restriction %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003304 }
3305 ctxt->container = name;
3306
3307 child = node->children;
3308 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003309 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3310 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003311 }
3312 subtype = NULL;
3313
3314 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003315 subtype = (xmlSchemaTypePtr)
3316 xmlSchemaParseAll(ctxt, schema, child);
3317 child = child->next;
3318 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003319 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003320 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3321 child = child->next;
3322 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003323 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003324 subtype = (xmlSchemaTypePtr)
3325 xmlSchemaParseSequence(ctxt, schema, child);
3326 child = child->next;
3327 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003328 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003329 subtype = (xmlSchemaTypePtr)
3330 xmlSchemaParseGroup(ctxt, schema, child);
3331 child = child->next;
3332 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003333 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003334 if (IS_SCHEMA(child, "simpleType")) {
3335 subtype = (xmlSchemaTypePtr)
3336 xmlSchemaParseSimpleType(ctxt, schema, child);
3337 child = child->next;
3338 type->baseType = subtype;
3339 }
3340 /*
3341 * Facets
3342 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003343 while ((IS_SCHEMA(child, "minInclusive")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003344 (IS_SCHEMA(child, "minExclusive")) ||
3345 (IS_SCHEMA(child, "maxInclusive")) ||
3346 (IS_SCHEMA(child, "maxExclusive")) ||
3347 (IS_SCHEMA(child, "totalDigits")) ||
3348 (IS_SCHEMA(child, "fractionDigits")) ||
3349 (IS_SCHEMA(child, "pattern")) ||
3350 (IS_SCHEMA(child, "enumeration")) ||
3351 (IS_SCHEMA(child, "whiteSpace")) ||
3352 (IS_SCHEMA(child, "length")) ||
3353 (IS_SCHEMA(child, "maxLength")) ||
3354 (IS_SCHEMA(child, "minLength"))) {
3355 facet = xmlSchemaParseFacet(ctxt, schema, child);
3356 if (facet != NULL) {
3357 if (lastfacet == NULL) {
3358 type->facets = facet;
3359 lastfacet = facet;
3360 } else {
3361 lastfacet->next = facet;
3362 lastfacet = facet;
3363 }
3364 lastfacet->next = NULL;
3365 }
3366 child = child->next;
3367 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003368 }
3369 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3370 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003371 xmlSchemaPErr2(ctxt, node, child,
3372 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
3373 "Restriction %s has unexpected content\n",
3374 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003375 }
3376 ctxt->container = oldcontainer;
3377 return (type);
3378}
3379
3380/**
3381 * xmlSchemaParseExtension:
3382 * @ctxt: a schema validation context
3383 * @schema: the schema being built
3384 * @node: a subtree containing XML Schema informations
3385 *
3386 * parse a XML schema Extension definition
3387 * *WARNING* this interface is highly subject to change
3388 *
3389 * Returns the type definition or NULL in case of error
3390 */
3391static xmlSchemaTypePtr
3392xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003393 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003394{
3395 xmlSchemaTypePtr type, subtype;
3396 xmlNodePtr child = NULL;
3397 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003398 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003399
3400 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3401 return (NULL);
3402
3403 oldcontainer = ctxt->container;
3404
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003405 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003406 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003407 if (type == NULL)
3408 return (NULL);
3409 type->node = node;
3410 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003411 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003412 ctxt->container = name;
3413
3414 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
3415 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003416 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
3417 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003418 }
3419 child = node->children;
3420 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003421 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3422 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003423 }
3424 subtype = NULL;
3425
3426 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003427 subtype = xmlSchemaParseAll(ctxt, schema, child);
3428 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003429 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003430 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3431 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003432 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003433 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3434 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003435 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003436 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3437 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003438 }
3439 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003440 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003441 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
3442 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003443 xmlSchemaPErr2(ctxt, node, child,
3444 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
3445 "Extension %s has unexpected content\n", type->name,
3446 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003447 }
3448 ctxt->container = oldcontainer;
3449 return (type);
3450}
3451
3452/**
3453 * xmlSchemaParseSimpleContent:
3454 * @ctxt: a schema validation context
3455 * @schema: the schema being built
3456 * @node: a subtree containing XML Schema informations
3457 *
3458 * parse a XML schema SimpleContent definition
3459 * *WARNING* this interface is highly subject to change
3460 *
3461 * Returns the type definition or NULL in case of error
3462 */
3463static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003464xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
3465 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003466{
3467 xmlSchemaTypePtr type, subtype;
3468 xmlNodePtr child = NULL;
3469 xmlChar name[30];
3470
3471 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3472 return (NULL);
3473
3474
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003475 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003476 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003477 if (type == NULL)
3478 return (NULL);
3479 type->node = node;
3480 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003481 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003482
3483 child = node->children;
3484 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003485 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3486 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003487 }
3488 subtype = NULL;
3489 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003490 subtype = (xmlSchemaTypePtr)
3491 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3492 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003493 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003494 subtype = (xmlSchemaTypePtr)
3495 xmlSchemaParseExtension(ctxt, schema, child);
3496 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003497 }
3498 type->subtypes = subtype;
3499 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003500 xmlSchemaPErr2(ctxt, node, child,
3501 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
3502 "SimpleContent %s has unexpected content\n",
3503 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003504 }
3505 return (type);
3506}
3507
3508/**
3509 * xmlSchemaParseComplexContent:
3510 * @ctxt: a schema validation context
3511 * @schema: the schema being built
3512 * @node: a subtree containing XML Schema informations
3513 *
3514 * parse a XML schema ComplexContent definition
3515 * *WARNING* this interface is highly subject to change
3516 *
3517 * Returns the type definition or NULL in case of error
3518 */
3519static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003520xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
3521 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003522{
3523 xmlSchemaTypePtr type, subtype;
3524 xmlNodePtr child = NULL;
3525 xmlChar name[30];
3526
3527 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3528 return (NULL);
3529
3530
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003531 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003532 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003533 if (type == NULL)
3534 return (NULL);
3535 type->node = node;
3536 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003537 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003538
3539 child = node->children;
3540 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003541 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3542 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003543 }
3544 subtype = NULL;
3545 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003546 subtype = (xmlSchemaTypePtr)
3547 xmlSchemaParseRestriction(ctxt, schema, child, 0);
3548 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003549 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003550 subtype = (xmlSchemaTypePtr)
3551 xmlSchemaParseExtension(ctxt, schema, child);
3552 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003553 }
3554 type->subtypes = subtype;
3555 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003556 xmlSchemaPErr2(ctxt, node, child,
3557 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
3558 "ComplexContent %s has unexpected content\n",
3559 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003560 }
3561 return (type);
3562}
3563
3564/**
3565 * xmlSchemaParseComplexType:
3566 * @ctxt: a schema validation context
3567 * @schema: the schema being built
3568 * @node: a subtree containing XML Schema informations
3569 *
3570 * parse a XML schema Complex Type definition
3571 * *WARNING* this interface is highly subject to change
3572 *
3573 * Returns the type definition or NULL in case of error
3574 */
3575static xmlSchemaTypePtr
3576xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3577 xmlNodePtr node)
3578{
3579 xmlSchemaTypePtr type, subtype;
3580 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003581 const xmlChar *name;
3582 const xmlChar *oldcontainer;
3583 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003584
3585 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3586 return (NULL);
3587
3588 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003589 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003590 if (name == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003591
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003592 snprintf(buf, 99, "anontype %d", ctxt->counter++ + 1);
3593 name = (const xmlChar *)buf;
3594 type = xmlSchemaAddType(ctxt, schema, name, NULL);
3595 } else {
3596 const xmlChar *local, *ns;
3597
3598 local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns);
3599 type = xmlSchemaAddType(ctxt, schema, local, ns);
Daniel Veillard4255d502002-04-16 15:50:10 +00003600 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003601 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 return (NULL);
3603 }
3604 type->node = node;
3605 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003606 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003607 ctxt->container = name;
3608
3609 child = node->children;
3610 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003611 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3612 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003613 }
3614 if (IS_SCHEMA(child, "simpleContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003615 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
3616 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003618 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
3619 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003621 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003622
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003623 if (IS_SCHEMA(child, "all")) {
3624 subtype = xmlSchemaParseAll(ctxt, schema, child);
3625 child = child->next;
3626 } else if (IS_SCHEMA(child, "choice")) {
3627 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3628 child = child->next;
3629 } else if (IS_SCHEMA(child, "sequence")) {
3630 subtype = xmlSchemaParseSequence(ctxt, schema, child);
3631 child = child->next;
3632 } else if (IS_SCHEMA(child, "group")) {
3633 subtype = xmlSchemaParseGroup(ctxt, schema, child);
3634 child = child->next;
3635 }
3636 if (subtype != NULL)
3637 type->subtypes = subtype;
3638 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 }
3640 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641 xmlSchemaPErr2(ctxt, node, child,
3642 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
3643 "ComplexType %s has unexpected content\n",
3644 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 }
3646 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003647 return (type);
3648}
3649
Daniel Veillard4255d502002-04-16 15:50:10 +00003650/**
3651 * xmlSchemaParseSchema:
3652 * @ctxt: a schema validation context
3653 * @node: a subtree containing XML Schema informations
3654 *
3655 * parse a XML schema definition from a node set
3656 * *WARNING* this interface is highly subject to change
3657 *
3658 * Returns the internal XML Schema structure built from the resource or
3659 * NULL in case of error
3660 */
3661static xmlSchemaPtr
3662xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3663{
3664 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003665 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003666 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003667 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003668
3669 if ((ctxt == NULL) || (node == NULL))
3670 return (NULL);
3671
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003672 nberrors = ctxt->nberrors;
3673 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 if (IS_SCHEMA(node, "schema")) {
3675 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003676 if (schema == NULL)
3677 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003678 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
3679 if (val != NULL) {
3680 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
3681 } else {
3682 schema->targetNamespace = NULL;
3683 }
3684 schema->id = xmlSchemaGetProp(ctxt, node, "id");
3685 schema->version = xmlSchemaGetProp(ctxt, node, "version");
3686 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003687 if (val != NULL) {
3688 if (xmlStrEqual(val, BAD_CAST "qualified"))
3689 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3690 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3691 xmlSchemaPErr2(ctxt, node, child,
3692 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
3693 "Invalid value %s for elementFormDefault\n",
3694 val, NULL);
3695 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003696 } else {
3697 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
3698 }
3699 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003700 if (val != NULL) {
3701 if (xmlStrEqual(val, BAD_CAST "qualified"))
3702 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
3703 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
3704 xmlSchemaPErr2(ctxt, node, child,
3705 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
3706 "Invalid value %s for attributeFormDefault\n",
3707 val, NULL);
3708 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003709 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003710
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003711 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
3712 } else {
3713 xmlDocPtr doc;
3714
3715 doc = node->doc;
3716
3717 if ((doc != NULL) && (doc->URL != NULL)) {
3718 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3719 XML_SCHEMAP_NOT_SCHEMA,
3720 "File %s is not a schemas", doc->URL, NULL);
3721 } else {
3722 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
3723 XML_SCHEMAP_NOT_SCHEMA,
3724 "File is not a schemas", NULL, NULL);
3725 }
3726 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003727 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003728 if (ctxt->nberrors != 0) {
3729 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003730 xmlSchemaFree(schema);
3731 schema = NULL;
3732 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003733 }
3734 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00003735#ifdef DEBUG
3736 if (schema == NULL)
3737 xmlGenericError(xmlGenericErrorContext,
3738 "xmlSchemaParse() failed\n");
3739#endif
3740
3741 return (schema);
3742}
3743
3744/************************************************************************
3745 * *
3746 * Validating using Schemas *
3747 * *
3748 ************************************************************************/
3749
3750/************************************************************************
3751 * *
3752 * Reading/Writing Schemas *
3753 * *
3754 ************************************************************************/
3755
3756/**
3757 * xmlSchemaNewParserCtxt:
3758 * @URL: the location of the schema
3759 *
3760 * Create an XML Schemas parse context for that file/resource expected
3761 * to contain an XML Schemas file.
3762 *
3763 * Returns the parser context or NULL in case of error
3764 */
3765xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003766xmlSchemaNewParserCtxt(const char *URL)
3767{
Daniel Veillard4255d502002-04-16 15:50:10 +00003768 xmlSchemaParserCtxtPtr ret;
3769
3770 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003771 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003772
3773 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3774 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003775 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3776 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003777 return (NULL);
3778 }
3779 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003780 ret->dict = xmlDictCreate();
3781 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003782 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003783 return (ret);
3784}
3785
3786/**
Daniel Veillard6045c902002-10-09 21:13:59 +00003787 * xmlSchemaNewMemParserCtxt:
3788 * @buffer: a pointer to a char array containing the schemas
3789 * @size: the size of the array
3790 *
3791 * Create an XML Schemas parse context for that memory buffer expected
3792 * to contain an XML Schemas file.
3793 *
3794 * Returns the parser context or NULL in case of error
3795 */
3796xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003797xmlSchemaNewMemParserCtxt(const char *buffer, int size)
3798{
Daniel Veillard6045c902002-10-09 21:13:59 +00003799 xmlSchemaParserCtxtPtr ret;
3800
3801 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003802 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003803
3804 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3805 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003806 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
3807 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00003808 return (NULL);
3809 }
3810 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3811 ret->buffer = buffer;
3812 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003813 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00003814 return (ret);
3815}
3816
3817/**
Daniel Veillard9d751502003-10-29 13:21:47 +00003818 * xmlSchemaNewDocParserCtxt:
3819 * @doc: a preparsed document tree
3820 *
3821 * Create an XML Schemas parse context for that document.
3822 * NB. The document may be modified during the parsing process.
3823 *
3824 * Returns the parser context or NULL in case of error
3825 */
3826xmlSchemaParserCtxtPtr
3827xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
3828{
3829 xmlSchemaParserCtxtPtr ret;
3830
3831 if (doc == NULL)
3832 return (NULL);
3833
3834 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
3835 if (ret == NULL) {
3836 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
3837 NULL);
3838 return (NULL);
3839 }
3840 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
3841 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00003842 ret->dict = xmlDictCreate();
Daniel Veillard9d751502003-10-29 13:21:47 +00003843
3844 return (ret);
3845}
3846
3847/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003848 * xmlSchemaFreeParserCtxt:
3849 * @ctxt: the schema parser context
3850 *
3851 * Free the resources associated to the schema parser context
3852 */
3853void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003854xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
3855{
Daniel Veillard4255d502002-04-16 15:50:10 +00003856 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003857 return;
Daniel Veillard6045c902002-10-09 21:13:59 +00003858 if (ctxt->doc != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003859 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003860 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003861 xmlFree(ctxt);
3862}
3863
3864/************************************************************************
3865 * *
3866 * Building the content models *
3867 * *
3868 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003869
Daniel Veillard4255d502002-04-16 15:50:10 +00003870/**
3871 * xmlSchemaBuildAContentModel:
3872 * @type: the schema type definition
3873 * @ctxt: the schema parser context
3874 * @name: the element name whose content is being built
3875 *
3876 * Generate the automata sequence needed for that type
3877 */
3878static void
3879xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003880 xmlSchemaParserCtxtPtr ctxt,
3881 const xmlChar * name)
3882{
Daniel Veillard4255d502002-04-16 15:50:10 +00003883 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003884 xmlGenericError(xmlGenericErrorContext,
3885 "Found unexpected type = NULL in %s content model\n",
3886 name);
3887 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003888 }
3889 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003890 case XML_SCHEMA_TYPE_ANY:
3891 /* TODO : handle the namespace too */
3892 /* TODO : make that a specific transition type */
3893 TODO ctxt->state =
3894 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
3895 BAD_CAST "*", NULL);
3896 break;
3897 case XML_SCHEMA_TYPE_ELEMENT:{
3898 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00003899
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003900 /* TODO : handle the namespace too */
3901 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003902
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003903 if (elem->maxOccurs >= UNBOUNDED) {
3904 if (elem->minOccurs > 1) {
3905 xmlAutomataStatePtr tmp;
3906 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003907
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003908 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3909 oldstate,
3910 NULL);
3911 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003912
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 counter = xmlAutomataNewCounter(ctxt->am,
3914 elem->minOccurs -
3915 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00003916
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003917 if (elem->refDecl != NULL) {
3918 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3919 elem->refDecl,
3920 ctxt,
3921 elem->refDecl->
3922 name);
3923 } else {
3924 ctxt->state =
3925 xmlAutomataNewTransition(ctxt->am,
3926 ctxt->state, NULL,
3927 elem->name, type);
3928 }
3929 tmp = ctxt->state;
3930 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3931 counter);
3932 ctxt->state =
3933 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
3934 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00003935
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003936 } else {
3937 if (elem->refDecl != NULL) {
3938 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3939 elem->refDecl,
3940 ctxt,
3941 elem->refDecl->
3942 name);
3943 } else {
3944 ctxt->state =
3945 xmlAutomataNewTransition(ctxt->am,
3946 ctxt->state, NULL,
3947 elem->name, type);
3948 }
3949 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3950 oldstate);
3951 if (elem->minOccurs == 0) {
3952 /* basically an elem* */
3953 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3954 ctxt->state);
3955 }
3956 }
3957 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
3958 xmlAutomataStatePtr tmp;
3959 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00003960
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003961 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
3962 oldstate, NULL);
3963 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00003964
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003965 counter = xmlAutomataNewCounter(ctxt->am,
3966 elem->minOccurs - 1,
3967 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003968
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003969 if (elem->refDecl != NULL) {
3970 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3971 elem->refDecl, ctxt,
3972 elem->refDecl->name);
3973 } else {
3974 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3975 ctxt->state,
3976 NULL,
3977 elem->name,
3978 type);
3979 }
3980 tmp = ctxt->state;
3981 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
3982 counter);
3983 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
3984 NULL,
3985 counter);
3986 if (elem->minOccurs == 0) {
3987 /* basically an elem? */
3988 xmlAutomataNewEpsilon(ctxt->am, oldstate,
3989 ctxt->state);
3990 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00003991
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003992 } else {
3993 if (elem->refDecl != NULL) {
3994 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
3995 elem->refDecl, ctxt,
3996 elem->refDecl->name);
3997 } else {
3998 ctxt->state = xmlAutomataNewTransition(ctxt->am,
3999 ctxt->state,
4000 NULL,
4001 elem->name,
4002 type);
4003 }
4004 if (elem->minOccurs == 0) {
4005 /* basically an elem? */
4006 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4007 ctxt->state);
4008 }
4009 }
4010 break;
4011 }
4012 case XML_SCHEMA_TYPE_SEQUENCE:{
4013 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004014
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004015 /*
4016 * If max and min occurances are default (1) then
4017 * simply iterate over the subtypes
4018 */
4019 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
4020 subtypes = type->subtypes;
4021 while (subtypes != NULL) {
4022 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4023 subtypes = subtypes->next;
4024 }
4025 } else {
4026 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004027
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004028 if (type->maxOccurs >= UNBOUNDED) {
4029 if (type->minOccurs > 1) {
4030 xmlAutomataStatePtr tmp;
4031 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004032
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004033 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4034 oldstate,
4035 NULL);
4036 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004037
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004038 counter = xmlAutomataNewCounter(ctxt->am,
4039 type->
4040 minOccurs - 1,
4041 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004042
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004043 subtypes = type->subtypes;
4044 while (subtypes != NULL) {
4045 xmlSchemaBuildAContentModel(subtypes, ctxt,
4046 name);
4047 subtypes = subtypes->next;
4048 }
4049 tmp = ctxt->state;
4050 xmlAutomataNewCountedTrans(ctxt->am, tmp,
4051 oldstate, counter);
4052 ctxt->state =
4053 xmlAutomataNewCounterTrans(ctxt->am, tmp,
4054 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00004055
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056 } else {
4057 subtypes = type->subtypes;
4058 while (subtypes != NULL) {
4059 xmlSchemaBuildAContentModel(subtypes, ctxt,
4060 name);
4061 subtypes = subtypes->next;
4062 }
4063 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
4064 oldstate);
4065 if (type->minOccurs == 0) {
4066 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4067 ctxt->state);
4068 }
4069 }
4070 } else if ((type->maxOccurs > 1)
4071 || (type->minOccurs > 1)) {
4072 xmlAutomataStatePtr tmp;
4073 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00004074
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004075 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
4076 oldstate,
4077 NULL);
4078 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00004079
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004080 counter = xmlAutomataNewCounter(ctxt->am,
4081 type->minOccurs -
4082 1,
4083 type->maxOccurs -
4084 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004085
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004086 subtypes = type->subtypes;
4087 while (subtypes != NULL) {
4088 xmlSchemaBuildAContentModel(subtypes, ctxt,
4089 name);
4090 subtypes = subtypes->next;
4091 }
4092 tmp = ctxt->state;
4093 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
4094 counter);
4095 ctxt->state =
4096 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
4097 counter);
4098 if (type->minOccurs == 0) {
4099 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4100 ctxt->state);
4101 }
Daniel Veillardb509f152002-04-17 16:28:10 +00004102
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004103 } else {
4104 subtypes = type->subtypes;
4105 while (subtypes != NULL) {
4106 xmlSchemaBuildAContentModel(subtypes, ctxt,
4107 name);
4108 subtypes = subtypes->next;
4109 }
4110 if (type->minOccurs == 0) {
4111 xmlAutomataNewEpsilon(ctxt->am, oldstate,
4112 ctxt->state);
4113 }
4114 }
4115 }
4116 break;
4117 }
4118 case XML_SCHEMA_TYPE_CHOICE:{
4119 xmlSchemaTypePtr subtypes;
4120 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00004121
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004122 start = ctxt->state;
4123 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00004124
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004125 /*
4126 * iterate over the subtypes and remerge the end with an
4127 * epsilon transition
4128 */
4129 if (type->maxOccurs == 1) {
4130 subtypes = type->subtypes;
4131 while (subtypes != NULL) {
4132 ctxt->state = start;
4133 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4134 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
4135 subtypes = subtypes->next;
4136 }
4137 } else {
4138 int counter;
4139 xmlAutomataStatePtr hop;
4140 int maxOccurs = type->maxOccurs == UNBOUNDED ?
4141 UNBOUNDED : type->maxOccurs - 1;
4142 int minOccurs =
4143 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00004144
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004145 /*
4146 * use a counter to keep track of the number of transtions
4147 * which went through the choice.
4148 */
4149 counter =
4150 xmlAutomataNewCounter(ctxt->am, minOccurs,
4151 maxOccurs);
4152 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00004153
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004154 subtypes = type->subtypes;
4155 while (subtypes != NULL) {
4156 ctxt->state = start;
4157 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4158 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
4159 subtypes = subtypes->next;
4160 }
4161 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
4162 counter);
4163 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
4164 counter);
4165 }
4166 if (type->minOccurs == 0) {
4167 xmlAutomataNewEpsilon(ctxt->am, start, end);
4168 }
4169 ctxt->state = end;
4170 break;
4171 }
4172 case XML_SCHEMA_TYPE_ALL:{
4173 xmlAutomataStatePtr start;
4174 xmlSchemaTypePtr subtypes;
4175 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
4176 int lax;
4177
4178 subtypes = type->subtypes;
4179 if (subtypes == NULL)
4180 break;
4181 start = ctxt->state;
4182 while (subtypes != NULL) {
4183 ctxt->state = start;
4184 elem = (xmlSchemaElementPtr) subtypes;
4185
4186 /* TODO : handle the namespace too */
4187 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
4188 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
4189 ctxt->state, elem->name, 1,
4190 1, subtypes);
4191 } else {
4192 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
4193 ctxt->state, elem->name,
4194 elem->minOccurs,
4195 elem->maxOccurs,
4196 subtypes);
4197 }
4198 subtypes = subtypes->next;
4199 }
4200 lax = type->minOccurs == 0;
4201 ctxt->state =
4202 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
4203 lax);
4204 break;
4205 }
4206 case XML_SCHEMA_TYPE_RESTRICTION:
4207 if (type->subtypes != NULL)
4208 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4209 break;
4210 case XML_SCHEMA_TYPE_EXTENSION:
4211 if (type->baseType != NULL) {
4212 xmlSchemaTypePtr subtypes;
4213
4214 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
4215 subtypes = type->subtypes;
4216 while (subtypes != NULL) {
4217 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
4218 subtypes = subtypes->next;
4219 }
4220 } else if (type->subtypes != NULL)
4221 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4222 break;
4223 case XML_SCHEMA_TYPE_GROUP:
4224 if (type->subtypes == NULL) {
4225 }
4226 case XML_SCHEMA_TYPE_COMPLEX:
4227 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
4228 if (type->subtypes != NULL)
4229 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
4230 break;
4231 default:
4232 xmlGenericError(xmlGenericErrorContext,
4233 "Found unexpected type %d in %s content model\n",
4234 type->type, name);
4235 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004236 }
4237}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004238
Daniel Veillard4255d502002-04-16 15:50:10 +00004239/**
4240 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004241 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00004242 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004243 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00004244 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004245 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00004246 */
4247static void
4248xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004249 xmlSchemaParserCtxtPtr ctxt,
4250 const xmlChar * name)
4251{
Daniel Veillard4255d502002-04-16 15:50:10 +00004252 xmlAutomataStatePtr start;
4253
Daniel Veillard4255d502002-04-16 15:50:10 +00004254 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004255 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004256 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004257 elem->contentType = XML_SCHEMA_CONTENT_ANY;
4258 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00004259 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004260 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004261 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004262 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
4263 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004265
4266#ifdef DEBUG_CONTENT
4267 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004268 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004269#endif
4270
Daniel Veillard4255d502002-04-16 15:50:10 +00004271 ctxt->am = xmlNewAutomata();
4272 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004273 xmlGenericError(xmlGenericErrorContext,
4274 "Cannot create automata for elem %s\n", name);
4275 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004276 }
4277 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
4278 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
4279 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00004280 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004281 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004282 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
4283 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004284 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004285 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
4286 "Content model of %s is not determinist:\n", name,
4287 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00004288 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00004289#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004290 xmlGenericError(xmlGenericErrorContext,
4291 "Content model of %s:\n", name);
4292 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004293#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00004294 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004295 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004296 xmlFreeAutomata(ctxt->am);
4297 ctxt->am = NULL;
4298}
4299
4300/**
4301 * xmlSchemaRefFixupCallback:
4302 * @elem: the schema element context
4303 * @ctxt: the schema parser context
4304 *
4305 * Free the resources associated to the schema parser context
4306 */
4307static void
4308xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 xmlSchemaParserCtxtPtr ctxt,
4310 const xmlChar * name,
4311 const xmlChar * context ATTRIBUTE_UNUSED,
4312 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00004313{
4314 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004315 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004316 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004318
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004319 if (elem->subtypes != NULL) {
4320 xmlSchemaPErr(ctxt, elem->node,
4321 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
4322 "Schemas: element %s have both ref and subtype\n",
4323 name, NULL);
4324 return;
4325 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004326 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00004327
4328 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004329 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_REF,
4330 "Schemas: element %s ref to %s not found\n",
4331 name, elem->ref);
4332 return;
4333 }
4334 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004335 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004336 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004337
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004338 if (elem->subtypes != NULL) {
4339 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
4340 "Schemas: element %s have both type and subtype\n",
4341 name, NULL);
4342 return;
4343 }
4344 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
4345 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00004346
4347 if (typeDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004348 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_UNKNOWN_TYPE,
4349 "Schemas: element %s type %s not found\n", name,
4350 elem->namedType);
4351 return;
4352 }
4353 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 }
4355}
4356
4357/**
4358 * xmlSchemaTypeFixup:
4359 * @typeDecl: the schema type definition
4360 * @ctxt: the schema parser context
4361 *
4362 * Fixes the content model of the type.
4363 */
4364static void
4365xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004366 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004367{
Daniel Veillard82bbbd42003-05-11 20:16:09 +00004368 if (typeDecl == NULL)
4369 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004370 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004371 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004373 switch (typeDecl->type) {
4374 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
4375 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
4376 if (typeDecl->subtypes != NULL)
4377 typeDecl->contentType =
4378 typeDecl->subtypes->contentType;
4379 break;
4380 }
4381 case XML_SCHEMA_TYPE_RESTRICTION:{
4382 if (typeDecl->subtypes != NULL)
4383 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004384
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004385 if (typeDecl->base != NULL) {
4386 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004387
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004388 baseType =
4389 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4390 typeDecl->baseNs);
4391 if (baseType == NULL) {
4392 xmlSchemaPErr(ctxt, typeDecl->node,
4393 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004394 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004395 name, typeDecl->base);
4396 }
4397 typeDecl->baseType = baseType;
4398 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004399 if (typeDecl->subtypes == NULL)
4400 if (typeDecl->baseType != NULL)
4401 typeDecl->contentType =
4402 typeDecl->baseType->contentType;
4403 else
4404 /* 1.1.1 */
4405 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004406 else if ((typeDecl->subtypes->subtypes == NULL) &&
4407 ((typeDecl->subtypes->type ==
4408 XML_SCHEMA_TYPE_ALL)
4409 || (typeDecl->subtypes->type ==
4410 XML_SCHEMA_TYPE_SEQUENCE)))
4411 /* 1.1.2 */
4412 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4413 else if ((typeDecl->subtypes->type ==
4414 XML_SCHEMA_TYPE_CHOICE)
4415 && (typeDecl->subtypes->subtypes == NULL))
4416 /* 1.1.3 */
4417 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4418 else {
4419 /* 1.2 and 2.X are applied at the other layer */
4420 typeDecl->contentType =
4421 XML_SCHEMA_CONTENT_ELEMENTS;
4422 }
4423 break;
4424 }
4425 case XML_SCHEMA_TYPE_EXTENSION:{
4426 xmlSchemaContentType explicitContentType;
4427 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00004428
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 if (typeDecl->base != NULL) {
4430 xmlSchemaTypePtr baseType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004431
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004432 baseType =
4433 xmlSchemaGetType(ctxt->schema, typeDecl->base,
4434 typeDecl->baseNs);
4435 if (baseType == NULL) {
4436 xmlSchemaPErr(ctxt, typeDecl->node,
4437 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Daniel Veillard4255d502002-04-16 15:50:10 +00004438 "Schemas: type %s base type %s not found\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004439 name, typeDecl->base);
4440 }
4441 typeDecl->baseType = baseType;
4442 }
4443 if (typeDecl->subtypes != NULL)
4444 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004445
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004446 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
4447 if (typeDecl->subtypes == NULL)
4448 /* 1.1.1 */
4449 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4450 else if ((typeDecl->subtypes->subtypes == NULL) &&
4451 ((typeDecl->subtypes->type ==
4452 XML_SCHEMA_TYPE_ALL)
4453 || (typeDecl->subtypes->type ==
4454 XML_SCHEMA_TYPE_SEQUENCE)))
4455 /* 1.1.2 */
4456 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
4457 else if ((typeDecl->subtypes->type ==
4458 XML_SCHEMA_TYPE_CHOICE)
4459 && (typeDecl->subtypes->subtypes == NULL))
4460 /* 1.1.3 */
4461 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004462
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004463 base = xmlSchemaGetType(ctxt->schema, typeDecl->base,
4464 typeDecl->baseNs);
4465 if (base == NULL) {
4466 xmlSchemaPErr(ctxt, typeDecl->node,
4467 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
4468 "Schemas: base type %s of type %s not found\n",
4469 typeDecl->base, name);
4470 return;
4471 }
4472 xmlSchemaTypeFixup(base, ctxt, NULL);
4473 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
4474 /* 2.1 */
4475 typeDecl->contentType = base->contentType;
4476 } else if (base->contentType ==
4477 XML_SCHEMA_CONTENT_EMPTY) {
4478 /* 2.2 imbitable ! */
4479 typeDecl->contentType =
4480 XML_SCHEMA_CONTENT_ELEMENTS;
4481 } else {
4482 /* 2.3 imbitable pareil ! */
4483 typeDecl->contentType =
4484 XML_SCHEMA_CONTENT_ELEMENTS;
4485 }
4486 break;
4487 }
4488 case XML_SCHEMA_TYPE_COMPLEX:{
4489 if (typeDecl->subtypes == NULL) {
4490 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4491 } else {
4492 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4493 typeDecl->contentType =
4494 XML_SCHEMA_CONTENT_MIXED;
4495 else {
4496 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4497 NULL);
4498 if (typeDecl->subtypes != NULL)
4499 typeDecl->contentType =
4500 typeDecl->subtypes->contentType;
4501 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004502 if (typeDecl->attributes == NULL)
4503 typeDecl->attributes =
4504 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004505 }
4506 break;
4507 }
4508 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
4509 if (typeDecl->subtypes == NULL) {
4510 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
4511 } else {
4512 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
4513 typeDecl->contentType =
4514 XML_SCHEMA_CONTENT_MIXED;
4515 else {
4516 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
4517 NULL);
4518 if (typeDecl->subtypes != NULL)
4519 typeDecl->contentType =
4520 typeDecl->subtypes->contentType;
4521 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00004522 if (typeDecl->attributes == NULL)
4523 typeDecl->attributes =
4524 typeDecl->subtypes->attributes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004525 }
4526 break;
4527 }
4528 case XML_SCHEMA_TYPE_SEQUENCE:
4529 case XML_SCHEMA_TYPE_GROUP:
4530 case XML_SCHEMA_TYPE_ALL:
4531 case XML_SCHEMA_TYPE_CHOICE:
4532 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
4533 break;
4534 case XML_SCHEMA_TYPE_BASIC:
4535 case XML_SCHEMA_TYPE_ANY:
4536 case XML_SCHEMA_TYPE_FACET:
4537 case XML_SCHEMA_TYPE_SIMPLE:
4538 case XML_SCHEMA_TYPE_UR:
4539 case XML_SCHEMA_TYPE_ELEMENT:
4540 case XML_SCHEMA_TYPE_ATTRIBUTE:
4541 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4542 case XML_SCHEMA_TYPE_NOTATION:
4543 case XML_SCHEMA_TYPE_LIST:
4544 case XML_SCHEMA_TYPE_UNION:
4545 case XML_SCHEMA_FACET_MININCLUSIVE:
4546 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4547 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4548 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
4549 case XML_SCHEMA_FACET_TOTALDIGITS:
4550 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4551 case XML_SCHEMA_FACET_PATTERN:
4552 case XML_SCHEMA_FACET_ENUMERATION:
4553 case XML_SCHEMA_FACET_WHITESPACE:
4554 case XML_SCHEMA_FACET_LENGTH:
4555 case XML_SCHEMA_FACET_MAXLENGTH:
4556 case XML_SCHEMA_FACET_MINLENGTH:
4557 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004558 if (typeDecl->subtypes != NULL)
4559 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004560 break;
4561 }
4562 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004563#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004564 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004565 xmlGenericError(xmlGenericErrorContext,
4566 "Type of %s : %s:%d :", name,
4567 typeDecl->node->doc->URL,
4568 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004569 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004570 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00004571 }
Daniel Veillard8651f532002-04-17 09:06:27 +00004572 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 case XML_SCHEMA_CONTENT_SIMPLE:
4574 xmlGenericError(xmlGenericErrorContext, "simple\n");
4575 break;
4576 case XML_SCHEMA_CONTENT_ELEMENTS:
4577 xmlGenericError(xmlGenericErrorContext, "elements\n");
4578 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004579 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004580 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
4581 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004582 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 xmlGenericError(xmlGenericErrorContext, "empty\n");
4584 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004585 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004586 xmlGenericError(xmlGenericErrorContext, "mixed\n");
4587 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004588 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004589 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
4590 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004591 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004592 xmlGenericError(xmlGenericErrorContext, "basic\n");
4593 break;
4594 default:
4595 xmlGenericError(xmlGenericErrorContext,
4596 "not registered !!!\n");
4597 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00004598 }
4599#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004600}
4601
4602/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004603 * xmlSchemaCheckFacet:
4604 * @facet: the facet
4605 * @typeDecl: the schema type definition
4606 * @ctxt: the schema parser context or NULL
4607 * @name: name of the type
4608 *
4609 * Checks the default values types, especially for facets
4610 *
4611 * Returns 0 if okay or -1 in cae of error
4612 */
4613int
4614xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004615 xmlSchemaTypePtr typeDecl,
4616 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004617{
4618 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
4619 int ret = 0;
4620
4621 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004622 nonNegativeIntegerType =
4623 xmlSchemaGetPredefinedType(BAD_CAST "nonNegativeInteger",
4624 xmlSchemaNs);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004625 }
4626 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004627 case XML_SCHEMA_FACET_MININCLUSIVE:
4628 case XML_SCHEMA_FACET_MINEXCLUSIVE:
4629 case XML_SCHEMA_FACET_MAXINCLUSIVE:
4630 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
4631 /*
4632 * Okay we need to validate the value
4633 * at that point.
4634 */
4635 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004636
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 vctxt = xmlSchemaNewValidCtxt(NULL);
4638 if (vctxt == NULL)
4639 break;
4640 xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4641 facet->value);
4642 facet->val = vctxt->value;
4643 vctxt->value = NULL;
4644 if (facet->val == NULL) {
4645 /* error code */
4646 if (ctxt != NULL) {
4647 xmlSchemaPErr(ctxt, facet->node,
4648 XML_SCHEMAP_INVALID_FACET,
4649 "Schemas: type %s facet value %s invalid\n",
4650 name, facet->value);
4651 }
4652 ret = -1;
4653 }
4654 xmlSchemaFreeValidCtxt(vctxt);
4655 break;
4656 }
4657 case XML_SCHEMA_FACET_ENUMERATION:{
4658 /*
4659 * Okay we need to validate the value
4660 * at that point.
4661 */
4662 xmlSchemaValidCtxtPtr vctxt;
4663 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004664
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004665 vctxt = xmlSchemaNewValidCtxt(NULL);
4666 if (vctxt == NULL)
4667 break;
4668 tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
4669 facet->value);
4670 if (tmp != 0) {
4671 if (ctxt != NULL) {
4672 xmlSchemaPErr(ctxt, facet->node,
4673 XML_SCHEMAP_INVALID_ENUM,
4674 "Schemas: type %s enumeration value %s invalid\n",
4675 name, facet->value);
4676 }
4677 ret = -1;
4678 }
4679 xmlSchemaFreeValidCtxt(vctxt);
4680 break;
4681 }
4682 case XML_SCHEMA_FACET_PATTERN:
4683 facet->regexp = xmlRegexpCompile(facet->value);
4684 if (facet->regexp == NULL) {
4685 xmlSchemaPErr(ctxt, typeDecl->node,
4686 XML_SCHEMAP_REGEXP_INVALID,
4687 "Schemas: type %s facet regexp %s invalid\n",
4688 name, facet->value);
4689 ret = -1;
4690 }
4691 break;
4692 case XML_SCHEMA_FACET_TOTALDIGITS:
4693 case XML_SCHEMA_FACET_FRACTIONDIGITS:
4694 case XML_SCHEMA_FACET_LENGTH:
4695 case XML_SCHEMA_FACET_MAXLENGTH:
4696 case XML_SCHEMA_FACET_MINLENGTH:{
4697 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004698
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004699 tmp =
4700 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
4701 facet->value,
4702 &facet->val);
4703 if (tmp != 0) {
4704 /* error code */
4705 if (ctxt != NULL) {
4706 xmlSchemaPErr(ctxt, facet->node,
4707 XML_SCHEMAP_INVALID_FACET_VALUE,
4708 "Schemas: type %s facet value %s invalid\n",
4709 name, facet->value);
4710 }
4711 ret = -1;
4712 }
4713 break;
4714 }
4715 case XML_SCHEMA_FACET_WHITESPACE:{
4716 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
4717 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
4718 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
4719 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
4720 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
4721 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
4722 } else {
4723 if (ctxt != NULL) {
4724 xmlSchemaPErr(ctxt, facet->node,
4725 XML_SCHEMAP_INVALID_WHITE_SPACE,
4726 "Schemas: type %s whiteSpace value %s invalid\n",
4727 name, facet->value);
4728 }
4729 ret = -1;
4730 }
4731 }
4732 default:
4733 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004734 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004735 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004736}
4737
4738/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004739 * xmlSchemaCheckDefaults:
4740 * @typeDecl: the schema type definition
4741 * @ctxt: the schema parser context
4742 *
4743 * Checks the default values types, especially for facets
4744 */
4745static void
4746xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004747 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004748{
Daniel Veillard4255d502002-04-16 15:50:10 +00004749 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004750 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004751 if (typeDecl->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004752 if (typeDecl->facets != NULL) {
4753 xmlSchemaFacetPtr facet = typeDecl->facets;
4754
4755 while (facet != NULL) {
4756 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
4757 facet = facet->next;
4758 }
4759 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004760 }
4761}
4762
4763/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00004764 * xmlSchemaAttrGrpFixup:
4765 * @attrgrpDecl: the schema attribute definition
4766 * @ctxt: the schema parser context
4767 * @name: the attribute name
4768 *
4769 * Fixes finish doing the computations on the attributes definitions
4770 */
4771static void
4772xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004773 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00004774{
4775 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004776 name = attrgrpDecl->name;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004777 if (attrgrpDecl->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004778 return;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004779 if (attrgrpDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004780 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004781
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004782 ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
4783 attrgrpDecl->refNs);
4784 if (ref == NULL) {
4785 xmlSchemaPErr(ctxt, attrgrpDecl->node,
4786 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,
4787 "Schemas: attribute group %s reference %s not found\n",
4788 name, attrgrpDecl->ref);
4789 return;
4790 }
4791 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
4792 attrgrpDecl->attributes = ref->attributes;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004793 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004794 xmlSchemaPErr(ctxt, attrgrpDecl->node, XML_SCHEMAP_NOATTR_NOREF,
4795 "Schemas: attribute %s has no attributes nor reference\n",
4796 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00004797 }
4798}
4799
4800/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004801 * xmlSchemaAttrFixup:
4802 * @attrDecl: the schema attribute definition
4803 * @ctxt: the schema parser context
4804 * @name: the attribute name
4805 *
4806 * Fixes finish doing the computations on the attributes definitions
4807 */
4808static void
4809xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004810 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004811{
4812 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004813 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004814 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004815 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004816 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004817 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004818
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004819 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
4820 attrDecl->typeNs);
4821 if (type == NULL) {
4822 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_TYPE,
4823 "Schemas: attribute %s type %s not found\n",
4824 name, attrDecl->typeName);
4825 }
4826 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004827 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00004829
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004830 ref = xmlHashLookup2(ctxt->schema->attrDecl, attrDecl->ref,
4831 attrDecl->refNs);
4832 if (ref == NULL) {
4833 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_UNKNOWN_REF,
4834 "Schemas: attribute %s reference %s not found\n",
4835 name, attrDecl->ref);
4836 return;
4837 }
4838 xmlSchemaAttrFixup(ref, ctxt, NULL);
4839 attrDecl->subtypes = ref->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00004840 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004841 xmlSchemaPErr(ctxt, attrDecl->node, XML_SCHEMAP_NOTYPE_NOREF,
4842 "Schemas: attribute %s has no type nor reference\n",
4843 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004844 }
4845}
4846
4847/**
4848 * xmlSchemaParse:
4849 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004850 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004851 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00004852 * XML Shema struture which can be used to validate instances.
4853 * *WARNING* this interface is highly subject to change
4854 *
4855 * Returns the internal XML Schema structure built from the resource or
4856 * NULL in case of error
4857 */
4858xmlSchemaPtr
4859xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
4860{
4861 xmlSchemaPtr ret = NULL;
4862 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004863 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004864 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004865
4866 xmlSchemaInitTypes();
4867
Daniel Veillard6045c902002-10-09 21:13:59 +00004868 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00004869 return (NULL);
4870
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004871 nberrors = ctxt->nberrors;
4872 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004873 ctxt->counter = 0;
4874 ctxt->container = NULL;
4875
4876 /*
4877 * First step is to parse the input document into an DOM/Infoset
4878 */
Daniel Veillard6045c902002-10-09 21:13:59 +00004879 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004880 doc = xmlReadFile((const char *) ctxt->URL, NULL,
4881 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004882 if (doc == NULL) {
4883 xmlSchemaPErr(ctxt, NULL,
4884 XML_SCHEMAP_FAILED_LOAD,
4885 "xmlSchemaParse: could not load %s\n",
4886 ctxt->URL, NULL);
4887 return (NULL);
4888 }
Daniel Veillard6045c902002-10-09 21:13:59 +00004889 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004890 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
4891 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004892 if (doc == NULL) {
4893 xmlSchemaPErr(ctxt, NULL,
4894 XML_SCHEMAP_FAILED_PARSE,
4895 "xmlSchemaParse: could not parse\n",
4896 NULL, NULL);
4897 return (NULL);
4898 }
4899 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00004900 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00004901 } else if (ctxt->doc != NULL) {
4902 doc = ctxt->doc;
Daniel Veillard6045c902002-10-09 21:13:59 +00004903 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 xmlSchemaPErr(ctxt, NULL,
4905 XML_SCHEMAP_NOTHING_TO_PARSE,
4906 "xmlSchemaParse: could not parse\n",
4907 NULL, NULL);
4908 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004909 }
4910
4911 /*
4912 * Then extract the root and Schema parse it
4913 */
4914 root = xmlDocGetRootElement(doc);
4915 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004916 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4917 XML_SCHEMAP_NOROOT,
4918 "schemas has no root", NULL, NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004919 xmlFreeDoc(doc);
Daniel Veillard4255d502002-04-16 15:50:10 +00004920 return (NULL);
4921 }
4922
4923 /*
4924 * Remove all the blank text nodes
4925 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004926 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00004927
4928 /*
4929 * Then do the parsing for good
4930 */
4931 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00004932 if (ret == NULL) {
4933 xmlFreeDoc(doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004934 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00004935 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004936 ret->doc = doc;
4937
4938 /*
4939 * Then fix all the references.
4940 */
4941 ctxt->schema = ret;
4942 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004943 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004944
4945 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00004946 * Then fixup all attributes declarations
4947 */
4948 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
4949
4950 /*
4951 * Then fixup all attributes group declarations
4952 */
4953 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
4954 ctxt);
4955
4956 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00004957 * Then fixup all types properties
4958 */
4959 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
4960
4961 /*
4962 * Then build the content model for all elements
4963 */
4964 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004965 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004966
4967 /*
4968 * Then check the defaults part of the type like facets values
4969 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004970 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
4971 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004972
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004973 if (ctxt->nberrors != 0) {
4974 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004975 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004976 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004977 return (ret);
4978}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004979
Daniel Veillard4255d502002-04-16 15:50:10 +00004980/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00004981 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00004983 * @err: the error callback
4984 * @warn: the warning callback
4985 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00004986 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00004987 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00004988 */
4989void
4990xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004991 xmlSchemaValidityErrorFunc err,
4992 xmlSchemaValidityWarningFunc warn, void *ctx)
4993{
Daniel Veillard4255d502002-04-16 15:50:10 +00004994 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004995 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00004996 ctxt->error = err;
4997 ctxt->warning = warn;
4998 ctxt->userData = ctx;
4999}
5000
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005001/**
5002 * xmlSchemaFacetTypeToString:
5003 * @type: the facet type
5004 *
5005 * Convert the xmlSchemaTypeType to a char string.
5006 *
5007 * Returns the char string representation of the facet type if the
5008 * type is a facet and an "Internal Error" string otherwise.
5009 */
5010static const char *
5011xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
5012{
5013 switch (type) {
5014 case XML_SCHEMA_FACET_PATTERN:
5015 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005016 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005017 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005018 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005019 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005020 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005021 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005022 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005023 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005024 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005025 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005026 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005027 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005028 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005029 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005030 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005031 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005032 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005033 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005034 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005035 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005036 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005037 return ("fractionDigits");
5038 default:
5039 break;
5040 }
5041 return ("Internal Error");
5042}
5043
5044/**
5045 * xmlSchemaValidateFacets:
5046 * @ctxt: a schema validation context
5047 * @base: the base type
5048 * @facets: the list of facets to check
5049 * @value: the lexical repr of the value to validate
5050 * @val: the precomputed value
5051 *
5052 * Check a value against all facet conditions
5053 *
5054 * Returns 0 if the element is schemas valid, a positive error code
5055 * number otherwise and -1 in case of internal or API error.
5056 */
5057static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005058xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
5059 xmlSchemaTypePtr base,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005060 xmlSchemaFacetPtr facets, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005061{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005062 int ret = 0;
5063 int tmp = 0;
5064 xmlSchemaTypeType type;
5065 xmlSchemaFacetPtr facet = facets;
5066
5067 while (facet != NULL) {
5068 type = facet->type;
5069 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005070 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005071
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005072 while (facet != NULL) {
5073 tmp =
5074 xmlSchemaValidateFacet(base, facet, value,
5075 ctxt->value);
5076 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005077 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005078 }
5079 facet = facet->next;
5080 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005081 } else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082 tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005083
5084 if (tmp != 0) {
5085 ret = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005086 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 +00005087 }
5088 if (facet != NULL)
5089 facet = facet->next;
5090 }
5091 return (ret);
5092}
5093
Daniel Veillard4255d502002-04-16 15:50:10 +00005094/************************************************************************
5095 * *
5096 * Simple type validation *
5097 * *
5098 ************************************************************************/
5099
5100/**
5101 * xmlSchemaValidateSimpleValue:
5102 * @ctxt: a schema validation context
5103 * @type: the type declaration
5104 * @value: the value to validate
5105 *
5106 * Validate a value against a simple type
5107 *
5108 * Returns 0 if the value is valid, a positive error code
5109 * number otherwise and -1 in case of internal or API error.
5110 */
5111static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005112xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005113 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005114{
Daniel Veillard4255d502002-04-16 15:50:10 +00005115 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005116
Daniel Veillard4255d502002-04-16 15:50:10 +00005117 /*
5118 * First normalize the value accordingly to Schema Datatype
5119 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
5120 */
5121 /*
5122 * Then check the normalized value against the lexical space of the
5123 * type.
5124 */
5125 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005126 if (ctxt->value != NULL) {
5127 xmlSchemaFreeValue(ctxt->value);
5128 ctxt->value = NULL;
5129 }
5130 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
5131 ctxt->cur);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005132 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005133 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 +00005134 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005135 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005136 xmlSchemaTypePtr base;
5137 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005138
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005139 base = type->baseType;
5140 if (base != NULL) {
5141 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5142 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005143 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005144 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005145
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005146 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00005147 * Do not validate facets or attributes when working on
5148 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005149 */
5150 if (ctxt->schema != NULL) {
5151 if (ret == 0) {
5152 facet = type->facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005153 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005154 }
5155 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005157 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00005158
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005159 base = type->subtypes;
5160 if (base != NULL) {
5161 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5162 } else {
5163 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00005164 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005165 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005166 const xmlChar *cur, *end;
5167 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005168 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00005169
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005170 base = type->subtypes;
5171 if (base == NULL) {
5172 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
5173 "Internal: List type %s has no base type\n",
5174 type->name, NULL);
5175 return (-1);
5176 }
5177 cur = value;
5178 do {
William M. Brack76e95df2003-10-18 16:20:14 +00005179 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005180 cur++;
5181 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00005182 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005183 end++;
5184 if (end == cur)
5185 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005186 tmp = xmlStrndup(cur, end - cur);
5187 ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
5188 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005189 if (ret2 != 0)
5190 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 cur = end;
5192 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005193 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005194 TODO
5195 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005196 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005197}
5198
5199/************************************************************************
5200 * *
5201 * DOM Validation code *
5202 * *
5203 ************************************************************************/
5204
5205static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005206 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005207static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005208 xmlNodePtr elem,
5209 xmlSchemaAttributePtr attributes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005210static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005211 xmlNodePtr elem,
5212 xmlSchemaElementPtr elemDecl,
5213 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00005214
5215/**
5216 * xmlSchemaRegisterAttributes:
5217 * @ctxt: a schema validation context
5218 * @attrs: a list of attributes
5219 *
5220 * Register the list of attributes as the set to be validated on that element
5221 *
5222 * Returns -1 in case of error, 0 otherwise
5223 */
5224static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005225xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
5226{
Daniel Veillard4255d502002-04-16 15:50:10 +00005227 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005228 if ((attrs->ns != NULL) &&
5229 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
5230 attrs = attrs->next;
5231 continue;
5232 }
5233 if (ctxt->attrNr >= ctxt->attrMax) {
5234 xmlSchemaAttrStatePtr tmp;
Daniel Veillard4255d502002-04-16 15:50:10 +00005235
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005236 ctxt->attrMax *= 2;
5237 tmp = (xmlSchemaAttrStatePtr)
5238 xmlRealloc(ctxt->attr, ctxt->attrMax *
5239 sizeof(xmlSchemaAttrState));
5240 if (tmp == NULL) {
5241 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
5242 ctxt->attrMax /= 2;
5243 return (-1);
5244 }
5245 ctxt->attr = tmp;
5246 }
5247 ctxt->attr[ctxt->attrNr].attr = attrs;
5248 ctxt->attr[ctxt->attrNr].state = XML_SCHEMAS_ATTR_UNKNOWN;
5249 ctxt->attrNr++;
5250 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005252 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005253}
5254
5255/**
5256 * xmlSchemaCheckAttributes:
5257 * @ctxt: a schema validation context
5258 * @node: the node carrying it.
5259 *
5260 * Check that the registered set of attributes on the current node
5261 * has been properly validated.
5262 *
5263 * Returns 0 if validity constraints are met, 1 otherwise.
5264 */
5265static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005266xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5267{
Daniel Veillard4255d502002-04-16 15:50:10 +00005268 int ret = 0;
5269 int i;
5270
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005271 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
5272 if (ctxt->attr[i].attr == NULL)
5273 break;
5274 if (ctxt->attr[i].state == XML_SCHEMAS_ATTR_UNKNOWN) {
5275 ret = 1;
5276 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN, "Attribute %s on %s is unknown\n", ctxt->attr[i].attr->name, node->name);
5277 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005278 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005279 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005280}
5281
5282/**
5283 * xmlSchemaValidateSimpleContent:
5284 * @ctxt: a schema validation context
5285 * @elem: an element
5286 * @type: the type declaration
5287 *
5288 * Validate the content of an element expected to be a simple type
5289 *
5290 * Returns 0 if the element is schemas valid, a positive error code
5291 * number otherwise and -1 in case of internal or API error.
5292 */
5293static int
5294xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005295 xmlNodePtr node ATTRIBUTE_UNUSED)
5296{
Daniel Veillard4255d502002-04-16 15:50:10 +00005297 xmlNodePtr child;
5298 xmlSchemaTypePtr type, base;
5299 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00005300 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005301
5302 child = ctxt->node;
5303 type = ctxt->type;
5304
5305 /*
5306 * Validation Rule: Element Locally Valid (Type): 3.1.3
5307 */
5308 value = xmlNodeGetContent(child);
5309 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
5310 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005311 case XML_SCHEMA_TYPE_RESTRICTION:{
5312 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00005313
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005314 base = type->baseType;
5315 if (base != NULL) {
5316 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
5317 } else {
5318 TODO}
5319 if (ret == 0) {
5320 facet = type->facets;
5321 ret =
5322 xmlSchemaValidateFacets(ctxt, base, facet, value);
5323 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005324 if ((ret == 0) && (type->attributes != NULL)) {
5325 ret = xmlSchemaValidateAttributes(ctxt, node,
5326 type->attributes);
5327 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005328 break;
5329 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005330 case XML_SCHEMA_TYPE_EXTENSION:{
5331 TODO
5332 break;
5333 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005334 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005335 TODO
5336 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005337 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005338 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005339
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005340 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005341}
5342
5343/**
5344 * xmlSchemaValidateCheckNodeList
5345 * @nodelist: the list of nodes
5346 *
5347 * Check the node list is only made of text nodes and entities pointing
5348 * to text nodes
5349 *
5350 * Returns 1 if true, 0 if false and -1 in case of error
5351 */
5352static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005353xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
5354{
Daniel Veillard4255d502002-04-16 15:50:10 +00005355 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 if (nodelist->type == XML_ENTITY_REF_NODE) {
5357 TODO /* implement recursion in the entity content */
5358 }
5359 if ((nodelist->type != XML_TEXT_NODE) &&
5360 (nodelist->type != XML_COMMENT_NODE) &&
5361 (nodelist->type != XML_PI_NODE) &&
5362 (nodelist->type != XML_PI_NODE)) {
5363 return (0);
5364 }
5365 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005366 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005367 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005368}
5369
5370/**
5371 * xmlSchemaSkipIgnored:
5372 * @ctxt: a schema validation context
5373 * @type: the current type context
5374 * @node: the top node.
5375 *
5376 * Skip ignorable nodes in that context
5377 *
5378 * Returns the new sibling
5379 * number otherwise and -1 in case of internal or API error.
5380 */
5381static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00005382xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005383 xmlSchemaTypePtr type, xmlNodePtr node)
5384{
Daniel Veillard4255d502002-04-16 15:50:10 +00005385 int mixed = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005386
Daniel Veillard4255d502002-04-16 15:50:10 +00005387 /*
5388 * TODO complete and handle entities
5389 */
5390 mixed = ((type->contentType == XML_SCHEMA_CONTENT_MIXED) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005391 (type->contentType == XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS));
Daniel Veillard4255d502002-04-16 15:50:10 +00005392 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005393 ((node->type == XML_COMMENT_NODE) ||
5394 ((mixed == 1) && (node->type == XML_TEXT_NODE)) ||
5395 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
5396 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
5397 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005398 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005400}
5401
5402/**
5403 * xmlSchemaValidateCallback:
5404 * @ctxt: a schema validation context
5405 * @name: the name of the element detected (might be NULL)
5406 * @type: the type
5407 *
5408 * A transition has been made in the automata associated to an element
5409 * content model
5410 */
5411static void
5412xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005413 const xmlChar * name ATTRIBUTE_UNUSED,
5414 xmlSchemaTypePtr type, xmlNodePtr node)
5415{
Daniel Veillard4255d502002-04-16 15:50:10 +00005416 xmlSchemaTypePtr oldtype = ctxt->type;
5417 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005418
Daniel Veillard4255d502002-04-16 15:50:10 +00005419#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00005420 xmlGenericError(xmlGenericErrorContext,
5421 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005422 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005423#endif
5424 ctxt->type = type;
5425 ctxt->node = node;
5426 xmlSchemaValidateContent(ctxt, node);
5427 ctxt->type = oldtype;
5428 ctxt->node = oldnode;
5429}
5430
5431
5432#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005433
Daniel Veillard4255d502002-04-16 15:50:10 +00005434/**
5435 * xmlSchemaValidateSimpleRestrictionType:
5436 * @ctxt: a schema validation context
5437 * @node: the top node.
5438 *
5439 * Validate the content of a restriction type.
5440 *
5441 * Returns 0 if the element is schemas valid, a positive error code
5442 * number otherwise and -1 in case of internal or API error.
5443 */
5444static int
5445xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
5446 xmlNodePtr node)
5447{
5448 xmlNodePtr child;
5449 xmlSchemaTypePtr type;
5450 int ret;
5451
5452 child = ctxt->node;
5453 type = ctxt->type;
5454
5455 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005456 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005457 return (-1);
5458 }
5459 /*
5460 * Only text and text based entities references shall be found there
5461 */
5462 ret = xmlSchemaValidateCheckNodeList(child);
5463 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005464 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005465 return (-1);
5466 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005467 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 +00005468 return (-1);
5469 }
5470 ctxt->type = type->subtypes;
5471 xmlSchemaValidateContent(ctxt, node);
5472 ctxt->type = type;
5473 return (ret);
5474}
5475#endif
5476
5477/**
5478 * xmlSchemaValidateSimpleType:
5479 * @ctxt: a schema validation context
5480 * @node: the top node.
5481 *
5482 * Validate the content of an simple type.
5483 *
5484 * Returns 0 if the element is schemas valid, a positive error code
5485 * number otherwise and -1 in case of internal or API error.
5486 */
5487static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005488xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5489{
Daniel Veillard4255d502002-04-16 15:50:10 +00005490 xmlNodePtr child;
5491 xmlSchemaTypePtr type;
5492 xmlAttrPtr attr;
5493 int ret;
5494
5495 child = ctxt->node;
5496 type = ctxt->type;
5497
5498 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005499 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s\n", node->name, NULL);
5500 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005501 }
5502 /*
5503 * Only text and text based entities references shall be found there
5504 */
5505 ret = xmlSchemaValidateCheckNodeList(child);
5506 if (ret < 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005507 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateSimpleType %s content\n", node->name, NULL);
5508 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005509 } else if (ret == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005510 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE, "Element %s content is not a simple type\n", node->name, NULL);
5511 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005512 }
5513 /*
5514 * Validation Rule: Element Locally Valid (Type): 3.1.1
5515 */
5516 attr = node->properties;
5517 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005518 if ((attr->ns == NULL) ||
5519 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
5520 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5521 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
5522 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
5523 (!xmlStrEqual
5524 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
5525 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR, "Element %s: attribute %s should not be present\n", node->name, attr->name);
5526 return (ctxt->err);
5527 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005528 }
5529
5530 ctxt->type = type->subtypes;
5531 ret = xmlSchemaValidateSimpleContent(ctxt, node);
5532 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005533 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005534}
5535
5536/**
5537 * xmlSchemaValidateElementType:
5538 * @ctxt: a schema validation context
5539 * @node: the top node.
5540 *
5541 * Validate the content of an element type.
5542 * Validation Rule: Element Locally Valid (Complex Type)
5543 *
5544 * Returns 0 if the element is schemas valid, a positive error code
5545 * number otherwise and -1 in case of internal or API error.
5546 */
5547static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005548xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5549{
Daniel Veillard4255d502002-04-16 15:50:10 +00005550 xmlNodePtr child;
5551 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005552 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +00005553 xmlSchemaElementPtr decl;
5554 int ret, attrBase;
5555
5556 oldregexp = ctxt->regexp;
5557
5558 child = ctxt->node;
5559 type = ctxt->type;
5560
5561 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005562 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateElementType\n", node->name, NULL);
5563 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005564 }
5565 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005566 if (type->minOccurs > 0) {
5567 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING, "Element %s: missing child %s\n", node->name, type->name);
5568 }
5569 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005570 }
5571
5572 /*
5573 * Verify the element matches
5574 */
5575 if (!xmlStrEqual(child->name, type->name)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005576 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM, "Element %s: missing child %s found %s\n", node->name, type->name, child->name);
5577 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005578 }
5579 /*
5580 * Verify the attributes
5581 */
5582 attrBase = ctxt->attrBase;
5583 ctxt->attrBase = ctxt->attrNr;
5584 xmlSchemaRegisterAttributes(ctxt, child->properties);
5585 xmlSchemaValidateAttributes(ctxt, child, type->attributes);
5586 /*
5587 * Verify the element content recursively
5588 */
5589 decl = (xmlSchemaElementPtr) type;
5590 oldregexp = ctxt->regexp;
5591 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005592 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
5593 (xmlRegExecCallbacks)
5594 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005595#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005596 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005597#endif
5598 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005599 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
5600 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +00005601
5602 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005603 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005604#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005605 xmlGenericError(xmlGenericErrorContext,
5606 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005607#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005608 if (ret == 0) {
5609 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", node->name, NULL);
5610 } else if (ret < 0) {
5611 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failure\n", node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005612#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005613 } else {
5614 xmlGenericError(xmlGenericErrorContext,
5615 "Element %s content check succeeded\n",
5616 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005617
5618#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005619 }
5620 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00005621 }
5622 /*
5623 * Verify that all attributes were Schemas-validated
5624 */
5625 xmlSchemaCheckAttributes(ctxt, node);
5626 ctxt->attrNr = ctxt->attrBase;
5627 ctxt->attrBase = attrBase;
5628
5629 ctxt->regexp = oldregexp;
5630
5631 ctxt->node = child;
5632 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005634}
5635
5636/**
5637 * xmlSchemaValidateBasicType:
5638 * @ctxt: a schema validation context
5639 * @node: the top node.
5640 *
5641 * Validate the content of an element expected to be a basic type type
5642 *
5643 * Returns 0 if the element is schemas valid, a positive error code
5644 * number otherwise and -1 in case of internal or API error.
5645 */
5646static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005647xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5648{
Daniel Veillard4255d502002-04-16 15:50:10 +00005649 int ret;
5650 xmlNodePtr child, cur;
5651 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005652 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +00005653
5654 child = ctxt->node;
5655 type = ctxt->type;
5656
5657 if ((ctxt == NULL) || (type == NULL)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005658 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: xmlSchemaValidateBasicType\n", node->name, NULL);
5659 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005660 }
5661 /*
5662 * First check the content model of the node.
5663 */
5664 cur = child;
5665 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005666 switch (cur->type) {
5667 case XML_TEXT_NODE:
5668 case XML_CDATA_SECTION_NODE:
5669 case XML_PI_NODE:
5670 case XML_COMMENT_NODE:
5671 case XML_XINCLUDE_START:
5672 case XML_XINCLUDE_END:
5673 break;
5674 case XML_ENTITY_REF_NODE:
5675 case XML_ENTITY_NODE:
5676 TODO break;
5677 case XML_ELEMENT_NODE:
5678 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: child %s should not be present\n", node->name, cur->name);
5679 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 case XML_ATTRIBUTE_NODE:
5681 case XML_DOCUMENT_NODE:
5682 case XML_DOCUMENT_TYPE_NODE:
5683 case XML_DOCUMENT_FRAG_NODE:
5684 case XML_NOTATION_NODE:
5685 case XML_HTML_DOCUMENT_NODE:
5686 case XML_DTD_NODE:
5687 case XML_ELEMENT_DECL:
5688 case XML_ATTRIBUTE_DECL:
5689 case XML_ENTITY_DECL:
5690 case XML_NAMESPACE_DECL:
5691#ifdef LIBXML_DOCB_ENABLED
5692 case XML_DOCB_DOCUMENT_NODE:
5693#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005694 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM, "Element %s: node type of node unexpected here\n", node->name, NULL);
5695 return (ctxt->err);
5696 }
5697 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005698 }
5699 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005700 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005701 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005702 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +00005703
5704 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005705 xmlSchemaFreeValue(ctxt->value);
5706 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005707 }
5708 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
5709 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005710 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00005711 if (ret != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005712 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 +00005713 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005714 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005715}
5716
5717/**
5718 * xmlSchemaValidateComplexType:
5719 * @ctxt: a schema validation context
5720 * @node: the top node.
5721 *
5722 * Validate the content of an element expected to be a complex type type
5723 * xmlschema-1.html#cvc-complex-type
5724 * Validation Rule: Element Locally Valid (Complex Type)
5725 *
5726 * Returns 0 if the element is schemas valid, a positive error code
5727 * number otherwise and -1 in case of internal or API error.
5728 */
5729static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005730xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5731{
Daniel Veillard4255d502002-04-16 15:50:10 +00005732 xmlNodePtr child;
Daniel Veillard8651f532002-04-17 09:06:27 +00005733 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005734 int ret;
5735
5736 child = ctxt->node;
5737 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005738 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005739
Daniel Veillard4255d502002-04-16 15:50:10 +00005740 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005741 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005742 if (type->baseType != NULL) {
5743 } else if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005744 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is supposed to be empty\n", node->name, NULL);
5745 }
5746 if (type->attributes != NULL) {
5747 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5748 }
5749 subtype = type->subtypes;
5750 while (subtype != NULL) {
5751 ctxt->type = subtype;
5752 xmlSchemaValidateComplexType(ctxt, node);
5753 subtype = subtype->next;
5754 }
5755 break;
5756 case XML_SCHEMA_CONTENT_ELEMENTS:
5757 case XML_SCHEMA_CONTENT_MIXED:
5758 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
5759 /*
5760 * Skip ignorable nodes in that context
5761 */
5762 child = xmlSchemaSkipIgnored(ctxt, type, child);
5763 while (child != NULL) {
5764 if (child->type == XML_ELEMENT_NODE) {
5765 ret = xmlRegExecPushString(ctxt->regexp,
5766 child->name, child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005767#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005768 if (ret < 0)
5769 xmlGenericError(xmlGenericErrorContext,
5770 " --> %s Error\n", child->name);
5771 else
5772 xmlGenericError(xmlGenericErrorContext,
5773 " --> %s\n", child->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005774#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005775 }
5776 child = child->next;
5777 /*
5778 * Skip ignorable nodes in that context
5779 */
5780 child = xmlSchemaSkipIgnored(ctxt, type, child);
5781 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005782 if (type->attributes != NULL) {
5783 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5784 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005785 break;
5786 case XML_SCHEMA_CONTENT_BASIC:{
5787 if (type->subtypes != NULL) {
5788 ctxt->type = type->subtypes;
5789 xmlSchemaValidateComplexType(ctxt, node);
5790 }
5791 if (type->baseType != NULL) {
5792 ctxt->type = type->baseType;
5793 xmlSchemaValidateBasicType(ctxt, node);
5794 }
5795 if (type->attributes != NULL) {
5796 xmlSchemaValidateAttributes(ctxt, node,
5797 type->attributes);
5798 }
5799 ctxt->type = type;
5800 break;
5801 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005802 case XML_SCHEMA_CONTENT_SIMPLE:{
5803 if (type->subtypes != NULL) {
5804 ctxt->type = type->subtypes;
5805 xmlSchemaValidateComplexType(ctxt, node);
5806 }
5807 if (type->baseType != NULL) {
5808 ctxt->type = type->baseType;
5809 xmlSchemaValidateComplexType(ctxt, node);
5810 }
5811 if (type->attributes != NULL) {
5812 xmlSchemaValidateAttributes(ctxt, node,
5813 type->attributes);
5814 }
5815 ctxt->type = type;
5816 break;
5817 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 default:
5819 TODO xmlGenericError(xmlGenericErrorContext,
5820 "unimplemented content type %d\n",
5821 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005822 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005823 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005824}
5825
5826/**
5827 * xmlSchemaValidateContent:
5828 * @ctxt: a schema validation context
5829 * @elem: an element
5830 * @type: the type declaration
5831 *
5832 * Validate the content of an element against the type.
5833 *
5834 * Returns 0 if the element is schemas valid, a positive error code
5835 * number otherwise and -1 in case of internal or API error.
5836 */
5837static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005838xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
5839{
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 xmlNodePtr child;
5841 xmlSchemaTypePtr type;
5842
5843 child = ctxt->node;
5844 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005845 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00005846
Daniel Veillarde19fc232002-04-22 16:01:24 +00005847 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
Daniel Veillard82bbbd42003-05-11 20:16:09 +00005848 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +00005849
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005851 case XML_SCHEMA_TYPE_ANY:
5852 /* Any type will do it, fine */
5853 TODO /* handle recursivity */
5854 break;
5855 case XML_SCHEMA_TYPE_COMPLEX:
5856 xmlSchemaValidateComplexType(ctxt, node);
5857 break;
5858 case XML_SCHEMA_TYPE_ELEMENT:{
5859 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
5860
5861 /*
5862 * Handle element reference here
5863 */
5864 if (decl->ref != NULL) {
5865 if (decl->refDecl == NULL) {
5866 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL, "Internal error: element reference %s not resolved\n", decl->ref, NULL);
5867 return (-1);
5868 }
5869 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
5870 decl = decl->refDecl;
5871 }
5872 xmlSchemaValidateElementType(ctxt, node);
5873 ctxt->type = type;
5874 break;
5875 }
5876 case XML_SCHEMA_TYPE_BASIC:
5877 xmlSchemaValidateBasicType(ctxt, node);
5878 break;
5879 case XML_SCHEMA_TYPE_FACET:
5880 TODO break;
5881 case XML_SCHEMA_TYPE_SIMPLE:
5882 xmlSchemaValidateSimpleType(ctxt, node);
5883 break;
5884 case XML_SCHEMA_TYPE_SEQUENCE:
5885 TODO break;
5886 case XML_SCHEMA_TYPE_CHOICE:
5887 TODO break;
5888 case XML_SCHEMA_TYPE_ALL:
5889 TODO break;
5890 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
5891 TODO break;
5892 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5893 TODO break;
5894 case XML_SCHEMA_TYPE_UR:
5895 TODO break;
5896 case XML_SCHEMA_TYPE_RESTRICTION:
5897 /*xmlSchemaValidateRestrictionType(ctxt, node); */
5898 TODO break;
5899 case XML_SCHEMA_TYPE_EXTENSION:
5900 TODO break;
5901 case XML_SCHEMA_TYPE_ATTRIBUTE:
5902 TODO break;
5903 case XML_SCHEMA_TYPE_GROUP:
5904 TODO break;
5905 case XML_SCHEMA_TYPE_NOTATION:
5906 TODO break;
5907 case XML_SCHEMA_TYPE_LIST:
5908 TODO break;
5909 case XML_SCHEMA_TYPE_UNION:
5910 TODO break;
5911 case XML_SCHEMA_FACET_MININCLUSIVE:
5912 TODO break;
5913 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5914 TODO break;
5915 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5916 TODO break;
5917 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5918 TODO break;
5919 case XML_SCHEMA_FACET_TOTALDIGITS:
5920 TODO break;
5921 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5922 TODO break;
5923 case XML_SCHEMA_FACET_PATTERN:
5924 TODO break;
5925 case XML_SCHEMA_FACET_ENUMERATION:
5926 TODO break;
5927 case XML_SCHEMA_FACET_WHITESPACE:
5928 TODO break;
5929 case XML_SCHEMA_FACET_LENGTH:
5930 TODO break;
5931 case XML_SCHEMA_FACET_MAXLENGTH:
5932 TODO break;
5933 case XML_SCHEMA_FACET_MINLENGTH:
5934 TODO break;
5935 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5936 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +00005937 }
5938 xmlSchemaValidateAttributes(ctxt, node, type->attributes);
5939
5940 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005941 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005942 ctxt->node = ctxt->node->next;
5943 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005944 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005945}
5946
5947/**
5948 * xmlSchemaValidateType:
5949 * @ctxt: a schema validation context
5950 * @elem: an element
5951 * @type: the list of type declarations
5952 *
5953 * Validate the content of an element against the types.
5954 *
5955 * Returns 0 if the element is schemas valid, a positive error code
5956 * number otherwise and -1 in case of internal or API error.
5957 */
5958static int
5959xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005960 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
5961{
Daniel Veillard4255d502002-04-16 15:50:10 +00005962 xmlChar *nil;
5963
Daniel Veillard2db8c122003-07-08 12:16:59 +00005964 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005965 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +00005966
Daniel Veillard4255d502002-04-16 15:50:10 +00005967 /*
5968 * 3.3.4 : 2
5969 */
5970 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005971 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT, "Element %s is abstract\n", elem->name, NULL);
5972 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00005973 }
5974 /*
5975 * 3.3.4: 3
5976 */
5977 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
5978 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005979 /* 3.3.4: 3.2 */
5980 if (xmlStrEqual(nil, BAD_CAST "true")) {
5981 if (elem->children != NULL) {
5982 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY, "Element %s is not empty\n", elem->name, NULL);
5983 return (ctxt->err);
5984 }
5985 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
5986 (elemDecl->value != NULL)) {
5987 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT, "Empty element %s cannot get a fixed value\n", elem->name, NULL);
5988 return (ctxt->err);
5989 }
5990 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005991 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005992 /* 3.3.4: 3.1 */
5993 if (nil != NULL) {
5994 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE, "Element %s with xs:nil but not nillable\n", elem->name, NULL);
5995 xmlFree(nil);
5996 return (ctxt->err);
5997 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005998 }
5999
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006000 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +00006001
6002 ctxt->type = elemDecl->subtypes;
6003 ctxt->node = elem->children;
6004 xmlSchemaValidateContent(ctxt, elem);
6005 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006006
6007 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006008}
6009
6010
6011/**
6012 * xmlSchemaValidateAttributes:
6013 * @ctxt: a schema validation context
6014 * @elem: an element
6015 * @attributes: the list of attribute declarations
6016 *
6017 * Validate the attributes of an element.
6018 *
6019 * Returns 0 if the element is schemas valid, a positive error code
6020 * number otherwise and -1 in case of internal or API error.
6021 */
6022static int
6023xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006024 xmlSchemaAttributePtr attributes)
6025{
Daniel Veillard4255d502002-04-16 15:50:10 +00006026 int i, ret;
6027 xmlAttrPtr attr;
6028 xmlChar *value;
Daniel Veillard13e04c62002-04-23 17:51:29 +00006029 xmlSchemaAttributeGroupPtr group = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006030
6031 if (attributes == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006032 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 while (attributes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006034 /*
6035 * Handle attribute groups
6036 */
6037 if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6038 group = (xmlSchemaAttributeGroupPtr) attributes;
6039 xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
6040 attributes = group->next;
6041 continue;
6042 }
6043 for (i = ctxt->attrBase; i < ctxt->attrNr; i++) {
6044 attr = ctxt->attr[i].attr;
6045 if (attr == NULL)
6046 continue;
6047 if (attributes->ref != NULL) {
6048 if (!xmlStrEqual(attr->name, attributes->ref))
6049 continue;
6050 if (attr->ns != NULL) {
6051 if ((attributes->refNs == NULL) ||
6052 (!xmlStrEqual(attr->ns->href, attributes->refNs)))
6053 continue;
6054 } else if (attributes->refNs != NULL) {
6055 continue;
6056 }
6057 } else {
6058 if (!xmlStrEqual(attr->name, attributes->name))
6059 continue;
6060 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006061 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006062 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006063 if (attr->ns == NULL) {
6064 /*
6065 * accept an unqualified attribute only if the declaration
6066 * is unqualified or if the schemas allowed it.
6067 */
6068 if ((attributes->targetNamespace != NULL) &&
6069 ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0))
6070 continue;
6071 } else {
6072 if (attributes->targetNamespace == NULL)
6073 continue;
6074 if (!xmlStrEqual(attributes->targetNamespace,
6075 attr->ns->href))
6076 continue;
6077 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006078 }
6079 ctxt->cur = (xmlNodePtr) attributes;
6080 if (attributes->subtypes == NULL) {
6081 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL, "Internal error: attribute %s type not resolved\n", attr->name, NULL);
6082 continue;
6083 }
6084 value = xmlNodeListGetString(elem->doc, attr->children, 1);
6085 ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
6086 value);
6087 if (ret != 0) {
6088 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_ATTRINVALID, "attribute %s on %s does not match type\n", attr->name, elem->name);
6089 } else {
6090 ctxt->attr[i].state = XML_SCHEMAS_ATTR_CHECKED;
6091 }
6092 if (value != NULL) {
6093 xmlFree(value);
6094 }
6095 }
6096 attributes = attributes->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006097 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006098 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006099}
6100
6101/**
6102 * xmlSchemaValidateElement:
6103 * @ctxt: a schema validation context
6104 * @elem: an element
6105 *
6106 * Validate an element in a tree
6107 *
6108 * Returns 0 if the element is schemas valid, a positive error code
6109 * number otherwise and -1 in case of internal or API error.
6110 */
6111static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006112xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
6113{
Daniel Veillard4255d502002-04-16 15:50:10 +00006114 xmlSchemaElementPtr elemDecl;
6115 int ret, attrBase;
6116
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006117 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006118 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6119 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006120 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006121 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6122 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006123 }
6124 /*
6125 * special case whe elementFormDefault is unqualified for top-level elem.
6126 */
6127 if ((elemDecl == NULL) && (elem->ns != NULL) &&
6128 (elem->parent != NULL) && (elem->parent->type != XML_ELEMENT_NODE) &&
6129 (xmlStrEqual(ctxt->schema->targetNamespace, elem->ns->href)) &&
6130 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6131 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6132 elem->name, NULL, NULL);
6133 }
6134
Daniel Veillard4255d502002-04-16 15:50:10 +00006135 /*
6136 * 3.3.4 : 1
6137 */
6138 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006139 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", elem->name, NULL);
6140 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006141 }
6142 if (elemDecl->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006143 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE, "Element %s has no type\n", elem->name, NULL);
6144 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006145 }
6146 /*
6147 * Verify the attributes
6148 */
6149 attrBase = ctxt->attrBase;
6150 ctxt->attrBase = ctxt->attrNr;
6151 xmlSchemaRegisterAttributes(ctxt, elem->properties);
6152 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->attributes);
6153 /*
6154 * Verify the element content recursively
6155 */
6156 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006157 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
6158 (xmlRegExecCallbacks)
6159 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00006160#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006161 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006162#endif
6163 }
6164 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006165 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006166 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006167#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006168 xmlGenericError(xmlGenericErrorContext,
6169 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006170#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006171 if (ret == 0) {
6172 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
6173 } else if (ret < 0) {
6174 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT, "Element %s content check failed\n", elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006175#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006176 } else {
6177 xmlGenericError(xmlGenericErrorContext,
6178 "Element %s content check succeeded\n",
6179 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00006180
6181#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006182 }
6183 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +00006184 }
6185 /*
6186 * Verify that all attributes were Schemas-validated
6187 */
6188 xmlSchemaCheckAttributes(ctxt, elem);
6189 ctxt->attrNr = ctxt->attrBase;
6190 ctxt->attrBase = attrBase;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006191
6192 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006193}
6194
6195/**
6196 * xmlSchemaValidateDocument:
6197 * @ctxt: a schema validation context
6198 * @doc: a parsed document tree
6199 *
6200 * Validate a document tree in memory.
6201 *
6202 * Returns 0 if the document is schemas valid, a positive error code
6203 * number otherwise and -1 in case of internal or API error.
6204 */
6205static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006206xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6207{
Daniel Veillard4255d502002-04-16 15:50:10 +00006208 xmlNodePtr root;
6209 xmlSchemaElementPtr elemDecl;
6210
6211 root = xmlDocGetRootElement(doc);
6212 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006213 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT, "document has no root\n", NULL, NULL);
6214 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006215 }
6216 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006217 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6218 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006219 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006220 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6221 root->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006222 /*
6223 * special case whe elementFormDefault is unqualified for top-level elem.
6224 */
6225 if ((elemDecl == NULL) && (root->ns != NULL) &&
6226 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
6227 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
6228 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
6229 root->name, NULL, NULL);
6230 }
6231
Daniel Veillard4255d502002-04-16 15:50:10 +00006232 if (elemDecl == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006233 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM, "Element %s not declared\n", root->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00006234 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_TOPLEVEL) == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006235 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL, "Root element %s not toplevel\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006236 }
6237 /*
6238 * Okay, start the recursive validation
6239 */
6240 xmlSchemaValidateElement(ctxt, root);
6241
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006242 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +00006243}
6244
6245/************************************************************************
6246 * *
6247 * SAX Validation code *
6248 * *
6249 ************************************************************************/
6250
6251/************************************************************************
6252 * *
6253 * Validation interfaces *
6254 * *
6255 ************************************************************************/
6256
6257/**
6258 * xmlSchemaNewValidCtxt:
6259 * @schema: a precompiled XML Schemas
6260 *
6261 * Create an XML Schemas validation context based on the given schema
6262 *
6263 * Returns the validation context or NULL in case of error
6264 */
6265xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006266xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
6267{
Daniel Veillard4255d502002-04-16 15:50:10 +00006268 xmlSchemaValidCtxtPtr ret;
6269
6270 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
6271 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006272 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006273 return (NULL);
6274 }
6275 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
6276 ret->schema = schema;
6277 ret->attrNr = 0;
6278 ret->attrMax = 10;
6279 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006280 sizeof
6281 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +00006282 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006283 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
6284 free(ret);
6285 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006286 }
6287 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
6288 return (ret);
6289}
6290
6291/**
6292 * xmlSchemaFreeValidCtxt:
6293 * @ctxt: the schema validation context
6294 *
6295 * Free the resources associated to the schema validation context
6296 */
6297void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006298xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
6299{
Daniel Veillard4255d502002-04-16 15:50:10 +00006300 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006301 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006302 if (ctxt->attr != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006303 xmlFree(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +00006304 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006305 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00006306 xmlFree(ctxt);
6307}
6308
6309/**
6310 * xmlSchemaSetValidErrors:
6311 * @ctxt: a schema validation context
6312 * @err: the error function
6313 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +00006314 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +00006315 *
6316 * Set the error and warning callback informations
6317 */
6318void
6319xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006320 xmlSchemaValidityErrorFunc err,
6321 xmlSchemaValidityWarningFunc warn, void *ctx)
6322{
Daniel Veillard4255d502002-04-16 15:50:10 +00006323 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006324 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006325 ctxt->error = err;
6326 ctxt->warning = warn;
6327 ctxt->userData = ctx;
6328}
6329
6330/**
6331 * xmlSchemaValidateDoc:
6332 * @ctxt: a schema validation context
6333 * @doc: a parsed document tree
6334 *
6335 * Validate a document tree in memory.
6336 *
6337 * Returns 0 if the document is schemas valid, a positive error code
6338 * number otherwise and -1 in case of internal or API error.
6339 */
6340int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006341xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
6342{
Daniel Veillard4255d502002-04-16 15:50:10 +00006343 int ret;
6344
6345 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006346 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006347
6348 ctxt->doc = doc;
6349 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006350 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00006351}
6352
6353/**
6354 * xmlSchemaValidateStream:
6355 * @ctxt: a schema validation context
6356 * @input: the input to use for reading the data
6357 * @enc: an optional encoding information
6358 * @sax: a SAX handler for the resulting events
6359 * @user_data: the context to provide to the SAX handler.
6360 *
6361 * Validate a document tree in memory.
6362 *
6363 * Returns 0 if the document is schemas valid, a positive error code
6364 * number otherwise and -1 in case of internal or API error.
6365 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006366int
Daniel Veillard4255d502002-04-16 15:50:10 +00006367xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006368 xmlParserInputBufferPtr input, xmlCharEncoding enc,
6369 xmlSAXHandlerPtr sax, void *user_data)
6370{
Daniel Veillard4255d502002-04-16 15:50:10 +00006371 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006372 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00006373 ctxt->input = input;
6374 ctxt->enc = enc;
6375 ctxt->sax = sax;
6376 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006377 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00006378}
6379
6380#endif /* LIBXML_SCHEMAS_ENABLED */